Dans les trois dernières vidéos on a vu comment lire un captcha à partir d'une image
et comment exécuter ce code sur github.
Et dans cette vidéo ce qu'on va faire c'est qu'on va mettre à disposition ce service, donc pour mon utilisation personnelle, via une api.
Et donc je vais vous montrer comment on peut faire une api très simple en PHP.
Et comme dans la vidéo précédente, il se trouve que j'ai déjà en projet un similaire qui... euh...
je vais pouvoir du coup copier et modifier pour pouvoir créer mon projet qu'on va faire dans cette vidéo.
Ce projet en question c'est le projet "tiktok-action-based-api", qui est le projet qui permet... en fait... d'appeler l'action github
qui permet de récupérer les vidéos et les informations aussi sur des auteurs des vidéos... du coup... tiktok qui sont postées.
Pour installer ce projet je vais prendre l'url ici,
je vais aller dans mon petit terminal, je fais un git clone de ce projet,
et je vais le changer... et du coup... pour lui donner un nouveau nom.
Il se trouve que mon projet d'action je l'avais appelé speechelo-captcha-reader. Et ben... ce projet-là en question,
vu que c'est l'API qui va appeler cette action, on va l'appeler speechelo-captcha-reader-api.
Et donc là on va là dedans... "speechelo-captcha-reader-api"... Donc là on est dans le projet.
Je vais retirer le remote du coup de mon de mon projet. Donc on va faire un "git remote remove origin".
Ensuite on va créer le repo github pour notre nouveau projet. Donc on va aller dans "new", on va aller là, on dit qu'il est public, hop !
On crée le repo, on met une petite étoile parce qu'on est rigolo, et ensuite on ajoute l'origine.
Ce qui fait que maintenant dès que je vais commit des fichiers euh... bah... ça partira... du coup... sur cette origine-là.
Ensuite on va ouvrir le code de ce projet. On utilise "code .", ça permet d'ouvrir VS Code, cette commande.
C'est très pratique. Je vous conseille d'avoir une commande du style,
que ça soit pour VS Code ou n'importe quelle autre de vos IDE, VS Code, elle est installée par défaut.
Et ce que je vais faire c'est que je vais virer tout ce qui concerne le projet que je vais pas avoir besoin.
C'est à dire tout ... bah... tout ça en gros à part la première ligne. Tac !
Je vais faire un petit peu de clean up, et je vous reprends après des j'ai supprimé les trucs qui m'intéressent pas.
Donc ça y est j'ai clean le projet de tout ce qui concernait spécifiquement l'autre projet que je ne vais pas réutiliser.
Donc on va rester avec ce fichier "index.php" que je vais vous expliquer dans quelques secondes.
Juste avant ça, ce qu'on va faire c'est qu'on va lancer le projet. Pour faire ça j'utilise le serveur interne de PHP,
J'ai déjà fait une vidéo à ce sujet. Si vous allez sur "apprendrephp.fr", ça va vous re diriger sur une playlist avec quelques vidéos PHP.
Et c'est la deuxième qui vous parle de comment on lance cette commande pour avoir le serveur interne de PHP qui lance un projet PHP.
Et si je l'exécute, cette commande,
on voit, du coup, qu'il me dit que le serveur interne de PHP est lancée.
Et ensuite, ce que je vais faire, c'est que pour aller ici, sur cette url, j'ai deux choix :
Soit je peux ouvrir, par exemple, un navigateur internet. Comme Google chrome, Firefox, Opéra, etc.
Ou soit je peux utiliser un autre outil qui est très efficace pour pour tester, en fait, nos APIs, pour voir si elles fonctionnent.
C'est postman ! Il y a plein d'équivalent à cet outil, il y en a beaucoup qui existent.
Mais donc moi je vais utiliser postman dans cette vidéo.
Et postman, ça permet d'envoyer des requêtes. C'est la même chose que fait nos navigateurs quand on se balade sur internet.
Euh... Sauf que l'avantage de postman et autres outils équivalent, c'est qu'on a beaucoup plus de contrôle sur ce qu'on envoie
ce qui fait que par exemple on peut simuler des envois de formulaires,
des choses comme ça qui seraient très difficile à faire sur un navigateur si on devait le faire directement depuis un navigateur.
Et là... donc là on voit ici que si j'appelle mon API, il ya 4... euh... 4 variables pour lesquelles j'ai affiché des valeurs.
On voit qu'il y "$calledEndPoint" qui est un slash. "$queryParameters" vide, "$_SERVER['HTTP_AUTHORIZATION']" qui est vide, et "$body" qui est vide.
Et donc je vais vous expliquer, en fait, ce que font chacune de ces variables, et dans quel cadre on aura envie de les utiliser.
La première c'est $calledEndPoint. On voit ici qu'elle a un "/",
Euh... c'est... ça veut dire... en fait... que j'ai appelé la racine du site.
D'ailleurs si on voit si je mets un "/" dans l'url on voit qu'elle aura toujours la valeur "/".
Alors que si je mets par exemple "toto", on va voir que ici à la place je vais avoir "/toto".
Donc ça me permet... d'avoir... d’accéder... quand on parle dans le cadre d'un site internet, à une différente page.
Ou quand on parle dans le cas d'une API, à une ressource différente.
Ensuite imaginons, je veux récupérer... euh... j'en sais rien, une liste de voitures.
Donc on peut mettre "/voiture". On va mettre au pluriel ("/voitures").
Donc là on voit qu'j'vais avoir le "/voitures" ici.
Et imaginons ces voitures je veux les filtrer par marque,
bah je peux par exemple faire un "?marque=renault".
J'crois que ça s'écrit comme ça ? J'sais pas comment ça s'écrit la marque "Renault".
Donc là si j'envoie sur "send", et ben on va voir que dans le $calledEndPoint j'ai toujours mon "/voitures"
Mais dans les $queryParameters on voit que j'ai "marque=renault".
Et c'est donc ça à quoi sert les query parameters,
en fait, c'est les paramètres qui sont passés dans l'url qui sont différents... du coup... de l'end point.
Donc notre ressource, ici, c'est la voiture et on veut les filtrer par la marque "renault".
Euh... Donc les paramètres, c'est ce qui est utilisé principalement pour faire des filtres, mais pas que.
Généralement c'est quand on veut faire de la récupération de données, si on a des paramètres à mettre,
on aura envie de les mettre, du coup, à cet endroit-là, donc dans les query parameters.
Mais par contre, si je veux créer une voiture, on aura plutôt envie d'utiliser le body de la request.
Pour faire ça on va dans "body", ici. On va aller dans "raw" Et là on peut envoyer ici les données qui permettent de créer une voiture.
Par exemple on va lui donner une marque qui va être "Renault", et on peut lui donner aussi...
par exemple... euh... qu'est-ce qu'on pourrait lui donner à une voiture ? Allez on va lui donner un nombre de roues.
Et on va lui donner 4. ça par exemple ça pourrait être quelque chose qui représente une voiture.
Et donc là si je clique sur "send", on va voir que dans le body on a bien la marque et des roues de la voiture qui sont envoyées.
Et donc ça le body c'est quelque chose, ouai, comme je disais,
qu'on aura plutôt tendance à utiliser quand on veut écrire des données, modifier, voire même supprimer, ça peut arriver.
Dès qu'on a besoin d'envoyer beaucoup d'informations on va les mettre dans le body.
Ensuite une API c'est quelque chose qu'on a envie de protéger,
parce qu'on n'a pas forcément envie que n'importe qui sur la planète, sans restriction, puisse appeler notre API à l'infini.
Donc pour faire ça, une des façons les plus les plus communes de le faire, c'est de protéger via un token.
Donc, c'est d'ailleurs, là, ici, ce qu'on va... en... récupérer dans "$_SERVER['HTTP_AUTHORIZATION']".
Donc là, il y a plusieurs types de tokens, euh... je vais utiliser un qui est très connu. C'est le "Bearer Token".
Donc là, si par exemple j'envoie un token qui va s'appeler "titi" par exemple, et que j'envoie,
On va voir que dans "Authorization", je récupère "Bearer titi".
Et en fait on va se baser sur ce token pour pouvoir protéger l'API.
Une API, au final, c'est ça. C'est des ressources qui sont mises à disposition des utilisateurs, qui peuvent être authentifiés par un token, ou pas authentifiés.
Ça dépend des API. Ces ressources mises à disposition des utilisateurs,
elles peuvent être éventuellement filtrés. Ou peut-être qu'il peut y avoir d'autres fonctionnalités, liées par exemple à des query parameters.
Et ces ressources peuvent être aussi modifiées, principalement via des choses qu'on met dans le body.
Une autre chose dont j'ai pas parlé, c'est y a les méthodes HTTP, qui sont GET, POST, PUT, machin etc.
Il y en a plein d'autres, on pourrait même en inventer si on a envie.
il y a des conventions là dessus Généralement dès qu'on veut récupérer des données,
on aura envie d'utiliser "GET". Dès qu'on veut créer de la donnée, on aura envie d'utiliser "POST".
Dès qu'on veut modifier une partie des données d'une ressource, on va utiliser "PATCH".
Dès qu'on va en supprimer, on va utiliser "DELETE", et cetera et cetera.
Je vous laisse vous renseigner sur les méthodes http individuellement pour savoir si pour votre route donnée,
donc pour votre url que vous allez créer, euh... par quelle méthode http ça serait plutôt intéressant de l'appeler.
Dans le cas cette vidéo, on va utiliser du "GET", parce qu'on va faire de la récupération de données, de la récupération de Captcha.
Et on va pas avoir besoin de body vu qu'on va pas modifier de la donnée.
Donc on va utiliser principalement, en fait, l'autorisation, les... peut-être les query parameters mais je pense même pas, et un end point.
Maintenant que vous avez compris dans les grandes lignes comment fonctionne une API.
Après, techniquement, ça va dépendre du langage, mais faut tout simplement se poser la question :
"Comment on récupére les query parameters ? Comment on récupère l'end point qui est appelé ? Comment on récupère le body de l'url (de la requête je voulais dire) ?"
Et après en fonction de langage que vous allez utiliser,
bah... vous allez tomber sur les solutions qui permettent de le faire dans le langage en question.
Il se trouve que (pour) PHP, le code qui permet de récupérer les informations pour créer une API,
quand on n'utilise pas de framework et qu'on le fait directement en natif comme moi j'ai fait ici dans ce code,
c'est mine de rien assez moche. C'est pas forcément évident à comprendre. Si vous voulez voir, en fait, comment ça fonctionne,
vous allez tout simplement cloner le projet, faire un "composer install",
lancer la petite commande que je vous ai montré pour lancer le serveur, et faire des "var_dump" pour comprendre (ce) que fait chacune de ces lignes.
Mais en PHP, principalement, pour... on va récupérer toutes ces informations dans la variable "$_SERVER".
Il y a beaucoup d'informations sur la requête.
On va récupérer, du coup, beaucoup de ces informations là dedans.
Mais par contre, un truc de PHP que moi je trouve vraiment bizarre, c'est que quand on veut récupérer le contenu du body, donc de la requête,
on doit faire un "file_get_contents('php://input')". C'est particulièrement moche mais c'est comme ça qu'on fait en PHP.
À noter aussi, qu'avant que le code arrive jusqu'à PHP,
si vous hébergez ça par exemple avec un Apache ou un Nginx, il faut penser qu'il y a le Apache ou le Nginx qui va faire des actions avant, qui peuvent peut-être modifier le header.
Je sais que, par exemple, il y a des cas de figure
où le "http authorization" peut disparaître de la requête.
Il faut faire un petit peu de config pour qu'il apparaisse et qu'il soit bien envoyé au code PHP.
Donc faut penser que dans tout ça, ce qu'on fait c'est une API web, donc va y avoir des problématiques du web, et des problématique dans notre langage de programmation,
et des fois des problématiques qui vont plus ou moins affecter les deux.
Donc maintenant qu'on a tout ça, on va définir... euh... comment on veut qu'on utilise notre API.
Donc pour rappel, notre projet, c'est de pouvoir lire un Captcha partir l'interface de Speechelo.
Ce qu'on récupère c'est une image via son url. Par exemple, j'ai cette image ici, qu'on y accède, via cette URL.
Et cette URL, on veut l'envoyer à notre action Github qui est ici, pour pouvoir récupérer la valeur du Captcha.
Donc là ici, c'est une récupération de données, qui peut être longue
parce qu'une action ça prend environ une minute, ou un peu plus, à s'exécuter.
Donc c'est long quand même pour une API; une API qui répond bout d'une minute.
Mais c'est la façon dont j'ai choisi de penser mon API.
il y avait une autre possibilité. Ça serait par exemple de faire mon API avec plusieurs routes.
C'est à dire une première route en "POST" qui permet de créer l'action.
Et ensuite une deuxième route en "GET" qui permet de récupérer l'état de l'action pour pouvoir en fait consulter l'API de manière périodique
pour savoir où est-ce qu'elle en est. "Est-ce que tu as fini ? Est ce que tu as fini ?"
Dès qu'elle a fini, bon... on peut récupérer le Captcha.
C'est une autre possibilité.
Mais ce niveau de complexité dans mon cas de figure n'est absolument pas nécessaire.
Dans mon cas, c'est vachement plus simple de faire une API synchrone qui répond bout d'une minute.
C'est long mais c'est pas grave. On s'en fiche.
Parce que dans mon cas de figure ça ne change strictement rien.
Je n'ai pas besoin de la complexité en terme de code qui est la création de plusieurs routes.
Donc dans notre cas on va créer une seule route en "GET".
Cette route, bah... vu qu'on récupère des Captchas, on pourrait l'appeler "/captcha".
Et ensuite vu qu'on veut récupérer les Captchas d'une certaine url,
cette url, on peut considérer ça comme étant l'id du Captcha.
Donc on pourrait envoyer directement la route ici "/captcha/{url}",
ce qui fait que je récupérerai cette url, et l'url c'est ce que j'enverrai à l'action.
Mais il se trouve, que, dans mon cas figure, mon API, elle aura qu'une ressource.
Donc est ce que je vais vraiment m'embêter à mettre le "/captcha" ?
Je pourrais très bien construire mon API de cette façon.
C'est à dire que dès qu'on appelle "localhost:8083", à noter que ça serait remplacé par un nom de domaine,
je vous expliquerai ça dans la prochaine vidéo,
qui sera sûrement un truc genre "get-captcha.ggio.fr", un truc comme ça,
et ensuite après le slash on peut considérer que c'est l'url.
Vu que mon API est relativement simple, je pense je vais partir sur cette option-là.
Je vais aller droit au but, puisque je vais avoir qu'une seule ressource, je vais même pas m’embêter à nommer ma route.
Donc on aura "{une url}/{une autre url}"
et on va, du coup... récupérer cette url pour l'envoyer aux actions et récupérer le Captcha.
La première chose qu'on va faire dans notre api, c'est de vérifier si l'utilisateur est connecté.
Donc là j'ai eu quelques classes que j'ai déjà créées.
Il y en a une c'est un "ConfigProvider", je l'ai appelé.
C'est quelque chose que j'utilise dans mes API.
C'est juste un truc qui permet de charger un fichier de config qui s'appelle "config.php".
Donc là si j'appelle mon code on va voir ça va pas fonctionner parce qu'il va me dire qu'il n'existe pas.
Et ce fichier de config, on va le construire à partir d'un exemple, qui est ici.
Donc dans ce fichier config, on a deux choses : on a le token qui va nous permetre de nous connecter;
qui sera en dur, qui sera toujours le même pour tous les utilisateurs.
Euh... je vais faire ça parce que c'est plus simple, vu que je serai le seul utilisateur de mon API.
Et ensuite on a le projet github qu'il faudra appeler pour pouvoir lire le Captcha.
Donc on va commencer par copier, du coup, ce fichier de config,
et on va lui donner une valeur de token. Mon token, je vais l'appeler "test" pour ma config de test,
et ensuite, bah dès que je mettrai ce projet en ligne, j'aurai un token secret que je générerai exprès pour... bah... en fait protéger mon API.
Donc là si j'appelle mon code, on va voir qu'il me dit que je suis pas autorisé.
Pour faire ce contrôle, si on retourne dans le code, on voit qu'ici qu'il récupère la config,
et il regarde si le "$authHeader", donc si le header "Authorization", il correspond à la valeur "Bearer {tokenDeMaConfig}".
Et là on voit que ce n'est pas le cas, du coup il m'envoie "non-autorisé".
Pour dire que c'est non-autorisé, il y a un code http qui s'appelle "401", qui permet de dire ça.
Et du coup les gens qui utilisent des API comprennent que 401 ça veut dire non-autorisé
euh... parce que eux ils connaissent les codes http.
Donc si vous voulez vous renseigner sur les codes http, vous pouvez aller sur google, vous tapez "code http", vous aurez la liste.
Et comme ça vous verrez les... les plus communs qui sont utilisées.
Principalement 200, 204, 403, 404, 403, euh... 500. C'est les plus communs.
Pour en citer que quelques-uns mais y en a plein d'autres.
Et donc là, ici, moi, j'ai mis une petite erreur "non autorisé" pour pouvoir que ça soit joli, ici, dans l'interface.
Mais c'est pas du tout obligatoire. Je pourrais totalement l'enlever et ça serait suffisant comme réponse.
Si par exemple, du coup, je relance. Hop ! Et là on voit qu'il me répond "401 non-autorisé",
Et je n'ai pas de réponse, ici, dans le body. Mon body est vide.
Mais ça, c'est quelque chose que je veux, faire parce que c'est suffisant. Je n'ai pas spécialement besoin d'afficher un message.
Le fait que ça me retourne un 401 est une information suffisante.
Donc maintenant si je veux être connecté, et ben je vais envoyer mon vrai token. Du coup je vais renvoyer le test.
Et là, on voit qu'il me répond "test", parce que dans mon code, j'ai défini que je voulais que l'API s'arrête en écrivant "test".
Et donc là, à ce niveau là, je suis connecté à mon API parce que j'ai envoyé le bon token.
Maintenant, la deuxième chose qu'on va faire, on va vérifier que l'url correspond à une url qu'on aura envie d'envoyer à l'action.
Parce qu'on n'a pas envie que... de faire en sorte que si quelqu'un nous envoie "truc",
eh ben ça envoie "truc" à l'action Github; c'est pas ça qu'on veut.
On veut appeler l'action Github uniquement si l'url est considérée comme valide.
Je viens d'écrire le code qui permet de valider l'url.
Je l'ai fait de manière relativement simpliste.
Je ne suis contenté de vérifier si l'url
commence par "https://app.blasteronline.com/assets/captcha",
et si ce n'est pas le cas, bah je réponds 400, et je vérifie que l'url se termine par ".jpeg", pour vérifier qu'on envoie bien une image.
Et si ce n'est pas le cas, je réponds 400.
400 c'est le code erreur http
qui dit en gros à l'utilisateur de l'API : "Hey mec, tu m'utilises pas correctement !
Envoie-moi quelque chose de correct, et comme ça après je comprendrais !"
Et on peut tester que ça fonctionne. Donc là, si on voit que j'appelle avec la bonne url, on voit qu'il me l'affiche.
Par contre, si je change mon domaine pour mettre n'importe quoi, eh ben il me répond 400 bad request.
Et si on voit que j'enlève la fin de l'url pour mettre n'importe quoi, il me répond 400 bad request.
D'ailleurs, j'ai aussi rajouté un autre code d'erreur. C'est que si jamais j'appelle l'API en mettant rien du tout,
il me retourne 404 not found parce qu'il connaît pas la page d'accueil de l'API. Elle n'en n'a pas.
Et pour faire ça c'est un tout simplement en vérifiant si le path est égal au path racine donc qui est "/".
Maintenant qu'on a validé que le Captcha est bien une url,
la chose suivante à faire et de l'envoyer à l'action.
Pour faire ça, dans la config je vous ai montré tout à l'heure, que j'avais le projet et le nom du compte.
Donc c'est à dire ici "speechelo-captcha-reader" et "pierreminiggio".
Ainsi que le token, que je vous ai pas révélé mais que j'ai rajouté à la config.
Avec ces informations-là, j'ai tout ce qu'il me faut pour appeler une action.
Donc là, on voit ici, que c'est cette petite classe qui appelle l'action,
qui est une petite fonction que j'ai récupérée, du coup, de mon projet que j'ai copié collé.
C'est pour ça que je l'ai copié collé d'ailleurs; c'est pour avoir justement... en fait... les... cette petite classe qui étaie déjà là, entre autres.
Et, aussi, on voit que j'appelle, ici, un autre projet qui est une bibliothèque que j'ai créée
qui permet de exécuter une action de manière synchrone.
Donc là, on voit qu'ici qu'on appelle le "get-captcha.yml" qu'on a construit dans la vidéo avant.
Et on voit ici, après il y a tout le code de la bibliothèque. Si vous voulez aller le voir, n'hésitez pas.
Euh... je sais plus si j'en avais déjà parlé dans une vidéo ou pas, de ce code.
Mais je l'ai utilisé pour d'autres de mes projets pour exécuter mes actions github euh... depuis... par... une API PHP.
Et donc là, bah... je vais le lancer, tout simplement, pour vous montrer.
Donc là, je clique sur "send", on voit que ça charge...
Et si on regarde sur les actions github, on voit qu'il y a une action qui est parti.
Et donc là c'est l'action qui va nous permettre de nous retourner le Captcha.
On voit que l'action s'est terminée.
Si on retourne ici, on voit que ça continue encore de tourner.
C'est parce qu'en fait, vu que je le lance en synchrone, il faut que je vérifie de temps en temps que l'action soit terminée.
Et je le fais toutes les minutes. Comme on voit ici toutes les 60 secondes.
Alors que même si l'action, ici, elle a pris un peu moins de temps, elle a pris 37 secondes,
j'ai fait un petit test avant qui a duré quarante et une secondes.
Vu que j'ai mis une minute, ça fait qu'on va devoir attendre quelques secondes de plus pour que le résultat apparaisse sous nos yeux.
Donc ça c'est quelque chose que je vais pouvoir réduire, en fait, en fonction de mes tests.
Le but, en fait, c'est de checker le moins souvent possible l'API de Github, pour éviter que j'utilise du quota pour rien.
Mais qui soit quand même au dessus en fait de monde montant habituel
ce qui fait que, au moins, idéalement j'ai besoin de checker qu'une seule fois.
Donc là, il se trouve que j'ai mis à une minute Mais là, du coup, on a le Captcha qui est arrivé, qui est ici.
Avec le fait qu'on a un petit "\n" qui traîne derrière, qu'on va devoir virer.
Mais là on récupère donc le Captcha.
Et ça y est ! J'ai fini le code de l'API. Je vais le relancer en attendant que je vous montre.
Donc là, on voit, ici, que je récupère la réponse de mon action.
Ce que je fais à cette réponse, c'est que je vais la trimer, ce qui me permet d'enlever le petit "\n" qui est juste à la fin.
Et je fais une vérification, je regarde que ma réponse fait exactement huit caractères de long.
Si c'est le cas, ça veut dire que ma réponse est bien un Captcha.
Si c'est bien un Captcha, je l'affiche. Et si ce n'est pas un Captcha, j'affiche un message d'erreur.
Enfin plus exactement un code d'erreur : 500, qui me dit : "Mon serveur a planté, il a fait n'importe quoi"
L'action vient de se terminer. Et si j'ouvre l'API, on voit bien que j'ai mon Captcha.
Le résultat de la lecture de mon Captcha qui est bien affiché dans le retour.
Et donc voilà ! On a une API qui fonctionne !
Dans la prochaine vidéo, je vais vous montrer comment je la mets en ligne.
Pour qu'elle soit accessible depuis le script qui sera capable de naviguer sur l'interface, plutôt qui est déjà capable de naviguer sur l'interface.
Parce que il va falloir juste que je rajoute la fonctionnalité de lire le Captcha.
Mais avant ça, oui, comme je disais, il va falloir que je le mette en ligne, et que je lui trouve un nom de domaine.
Et donc je vais vous expliquer comment je vais faire ça dans la prochaine vidéo.
Bon bah c'était Pierre ! J'espère que cette vidéo vous a plu !
J'espère que cette façon dont je vous présente en même temps que je suis en train de faire mes projets euh...
Bah ça vous plaît, et si c'est le cas n'hésitez pas à me le dire. Il y a les pouces bleus, il y a les commentaires.
Si vous avez des questions, n'hésitez pas comme d'hab dans les commentaires.
Et sur ce, c'était Pierre, et je vous dis à la prochaine ! Allez salut !