2009-04-07 12 views
29

私はこのようなURLを持っている:Cを使用してURLを解析する最適な方法は?

http://192.168.0.1:8080/servlet/rece 

私は値を取得するためのURLを解析したい:

IP: 192.168.0.1 
Port: 8080 
page: /servlet/rece 

はどのように私はそれを行うのですか?

+0

for Windows、CoInternetParseUrlを使用してください – Jichao

答えて

2

カスタムパーサーを記述するか、文字列置換関数の1つを使用して、セパレータ ':'を置き換えてからsscanf()を使用してください。

+15

カスタムパーサーが私には悪い考えであるように見える多くのトラップがあります。 – bortzmeyer

+0

@bortzmeye:それは提案を無効にしません。それはあいまいな推論です。また、カスタムパーザは、最も強力な/効率的/依存関係のないものです。 sscanfは間違っている方が簡単です。 – dirkgently

+4

「あなたが必要とするコードを書く」とはどういう意味ですか? – Spike0xff

9

regular expressionとすれば、簡単な方法が必要です。それ以外の場合はFLEX/BISONを使用してください。

また、私は、単純なコード使用sscanf関数をwrited URI parsing library

+1

実際には、多くのトラップ(httpとhttps、明示的なポート、パス内のエンコーディングなど)があるので、ライブラリを使用するのは妥当なことです。 – bortzmeyer

+0

こんにちは、私はこのようなURLのBNFを書いています。 URL = "http://" {IP} {PORT}? {ページ}? フレックスがURLを解析したファイルを生成しました。しかし、どのようにIP、PORT、PAGEのような個々の部品を取り出すのか。 URLから –

9

を使用することができます。私はそれを解析する基本的な方法が必要です。

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" 
+0

これはどのプラットフォームですか?私は[^:]のような正規表現をsscanf形式で入れることができるかどうかはわかりませんでした。 –

+0

私のプラットフォームは次のとおりです:uname -a Linux ubuntu 2.6.24-21-generic#1 SMP Tue Oct 21 23:43:45 UTC 2008 i686 GNU/Linux –

+4

[^:]はこの文脈では正規表現ではありません。 sscanf()の特別な書式指定子です。それは標準です。例えば、このマニュアルページ:を参照してください。 – unwind

22

は個人的に、私はHTParse.cモジュールfrom the W3C(これは、例えば、lynx Webブラウザで使用されている)を盗みます。次に、あなたのようなことを行うことができます。

十分に確立およびデバッグライブラリの使用方法についての重要なことは、ホストである場合、あなたは多くの正規表現は失敗(パースURLの典型的な トラップに分類されないということです
strncpy(hostname, HTParse(url, "", PARSE_HOST), size) 

IPアドレス、例えば、特にIPv6アドレス)。

+1

特に、IPv6ではコロンセパレータを使用しようとすると曖昧な場合があることに注意してください。例えば3ffe:0501 :: 1:2、それは2のポート、またはあなたのデフォルトポートの完全なアドレスです。 URLスペックは、これを扱っています。これは、あらかじめ書き込まれたライブラリもあります。 – bitmusher

+3

実際のあいまいさはありません。 URI標準であるRFC 3986は明確で、あなたの例は不正です(大括弧が必要です)。 – bortzmeyer

+2

ありがとう、これは慰めです。私はブラウザのアドレスバーのように、ユーザーが直面しているコードが大括弧なしのアドレスを受け入れていたという誤った印象のもとにいました。いくつかの一般的なブラウザのクイックツアーでは、これは当てはまりません。 – bitmusher

2

このサイズは小さくなり、私にとっては優れていましたhttp://draft.scyphus.co.jp/lang/c/url_parser.htmlちょうど2つのファイル(* .c、* .h)。
私はコード[1]を適合させなければならなかった。

[1]すべての関数は(PURL)をparsed_url_freeする(PURL)http_parsed_url_freeから呼び出し変更

//Rename the function called 
    //http_parsed_url_free(purl); 
    parsed_url_free(purl); 
+2

@ tremendows:優れたリンク。それは魅力のように働く。 –

+3

悲しいことに、優秀なコードは著作権で保護されているので、個人的なプロジェクト以外では使用しないでください。 –

+1

優秀なリンク。それは魅力のように動作します –

0

このCの要旨は、有用であり得ます。それはsscanfで純粋なCソリューションを実装します。

https://github.com/luismartingil/per.scripts/tree/master/c_parse_http_url

それは

// 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;} 
(...) 
+0

第三のif文はテストされません。第二のものが同じ意味を持っているので、これはポート/ページ – Risinek

9

を使用遅れる場合があり、...私が使用しているものを は、ある - Joyent/HTTP parser LIBから分離http_parser_parse_url()機能と必要なマクロ - うまく働いていました、 ~600 LOC。

+0

で問題を引き起こす可能性があります。 node.js HTTPパーサーlibは素晴らしいですし、HTTPリクエスト/レスポンスと何か関係があるかどうかは非常によくテストされています。 –

関連する問題