J'ai une URL comme celle-ci:
http://192.168.0.1:8080/servlet/rece
Je veux analyser l'URL pour obtenir les valeurs:
IP: 192.168.0.1
Port: 8080
page: /servlet/rece
Comment je fais ça?
Écrivez un analyseur personnalisé ou utilisez l'une des fonctions de remplacement de chaîne pour remplacer le séparateur ':', puis utilisez sscanf()
.
Personnellement, je vole le module HTParse.c
du W3C (il est utilisé dans le navigateur lynx Web, par exemple). Ensuite, vous pouvez faire des choses comme:
strncpy(hostname, HTParse(url, "", PARSE_Host), size)
L’important dans l’utilisation d’une bibliothèque bien établie et déboguée est de ne pas tomber dans les pièges Typiques de l’analyse d’URL (de nombreuses regexps échouent lorsque l’hôte est une adresse IP, par exemple spécialement une adresse IPv6).
Avec un expression régulière si vous voulez le moyen le plus simple. Sinon, utilisez FLEX / BISON .
Vous pouvez aussi utiliser une bibliothèque d’analyses URI
Peut-être en retard, ... Ce que j’ai utilisé, c’est - la fonction http_parser_parse_url()
et les macros requises séparées de l’analyseur Joyent/HTTP lib - qui a bien fonctionné, ~600
LOC.
J'ai écrit un code simple, utilisez sscanf. Je veux avoir un moyen de base pour l'analyser.
cat urlparse.c
#include <stdio.h>
int main(void)
{
const char text[] = "http://192.168.0.2:8888/servlet/rece";
char ip[100];
int port = 80;
char page[100];
sscanf(text, "http://%99[^:]:%99d/%99[^\n]", ip, &port, page);
printf("ip = \"%s\"\n", ip);
printf("port = \"%d\"\n", port);
printf("page = \"%s\"\n", page);
return 0;
}
./urlparse
ip = "192.168.0.2"
port = "8888"
page = "servlet/rece"
Celui-ci a une taille réduite et fonctionne parfaitement pour moi http://draft.scyphus.co.jp/lang/c/url_parser.html . Juste deux fichiers (* .c, * .h).
J'ai dû adapter le code [1].
[1] Remplacez tous les appels de fonction de http_parsed_url_free (purl) à parsed_url_free (purl).
//Rename the function called
//http_parsed_url_free(purl);
parsed_url_free(purl);
Libcurl a maintenant la fonction curl_url_get()
qui permet d'extraire l'hôte, le chemin, etc.
Exemple de code: https://curl.haxx.se/libcurl/c/parseurl.html
/* extract Host name from the parsed URL */
uc = curl_url_get(h, CURLUPART_Host, &Host, 0);
if(!uc) {
printf("Host name: %s\n", Host);
curl_free(Host);
}
Cet élément C pourrait être utile. Il implémente une solution C pure avec sscanf.
https://github.com/luismartingil/per.scripts/tree/master/c_parse_http_url
Il utilise
// Parsing the tmp_source char*
if (sscanf(tmp_source, "http://%99[^:]:%i/%199[^\n]", ip, &port, page) == 3) { succ_parsing = 1;}
else if (sscanf(tmp_source, "http://%99[^/]/%199[^\n]", ip, page) == 2) { succ_parsing = 1;}
else if (sscanf(tmp_source, "http://%99[^:]:%i[^\n]", ip, &port) == 2) { succ_parsing = 1;}
else if (sscanf(tmp_source, "http://%99[^\n]", ip) == 1) { succ_parsing = 1;}
(...)
J'ai écrit ça
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct
{
const char* protocol = 0;
const char* site = 0;
const char* port = 0;
const char* path = 0;
} URL_INFO;
URL_INFO* split_url(URL_INFO* info, const char* url)
{
if (!info || !url)
return NULL;
info->protocol = strtok(strcpy((char*)malloc(strlen(url)+1), url), "://");
info->site = strstr(url, "://");
if (info->site)
{
info->site += 3;
char* site_port_path = strcpy((char*)calloc(1, strlen(info->site) + 1), info->site);
info->site = strtok(site_port_path, ":");
info->site = strtok(site_port_path, "/");
}
else
{
char* site_port_path = strcpy((char*)calloc(1, strlen(url) + 1), url);
info->site = strtok(site_port_path, ":");
info->site = strtok(site_port_path, "/");
}
char* URL = strcpy((char*)malloc(strlen(url) + 1), url);
info->port = strstr(URL + 6, ":");
char* port_path = 0;
char* port_path_copy = 0;
if (info->port && isdigit(*(port_path = (char*)info->port + 1)))
{
port_path_copy = strcpy((char*)malloc(strlen(port_path) + 1), port_path);
char * r = strtok(port_path, "/");
if (r)
info->port = r;
else
info->port = port_path;
}
else
info->port = "80";
if (port_path_copy)
info->path = port_path_copy + strlen(info->port ? info->port : "");
else
{
char* path = strstr(URL + 8, "/");
info->path = path ? path : "/";
}
int r = strcmp(info->protocol, info->site) == 0;
if (r && info->port == "80")
info->protocol = "http";
else if (r)
info->protocol = "tcp";
return info;
}
Test
int main()
{
URL_INFO info;
split_url(&info, "ftp://192.168.0.1:8080/servlet/rece");
printf("Protocol: %s\nSite: %s\nPort: %s\nPath: %s\n", info.protocol, info.site, info.port, info.path);
return 0;
}
En dehors
Protocol: ftp
Site: 192.168.0.1
Port: 8080
Path: /servlet/rece