2016-09-10 13 views
0

私の教授がHTTPライブラリを使用できないと言ったので、私はHTTP要求を処理するJavaサーバを作成しています。 ..)。だから、私は正規表現を使ってリクエストを処理することに決めました。コード上で最初に起こるのは、要求の各行を取得し、それをパターンで処理する単一の文字列に変換することです。 POSTPUTHEADを、GET をDELETE:私だけのための例を実装する必要があります。私はアプリケーションを使用しています郵便番号、私のプログラムをテストするためのGoogle Chrome拡張機能。私は単一の文字列にそれを作った後、ここで配達員からの要求のいくつかの例は以下のとおりです。Regex for HTTP要求が動作しない場合がある

取得:

GET/HTTP/1.1ホスト:127.0.0.1:15000接続:キープアライブのCache-Control :no-cacheユーザエージェント:Mozilla/5.0(X11; Linux x86_64)AppleWebKit/537.36(GeckoのようなKHTML)Chrome/53.0.2785.101 Safari/537.36郵便番号:dd87e652-2b21-3632-30ad-ace26581d369受諾:/のAccept-エンコード:gzipでは、受け入れ言語をSDCH、収縮:EN-US、エン;ボディなしのq = 0.8

ポスト:

POST/HTTP/1.1ホスト:127.0.0.1:15000接続:キープアライブのContent-Length:0のCache-Control:キャッシュなし原産地:クローム拡張:// fhbjgbiflinjbdggehcddcbncdddomopのUser-Agent:Mozillaの/ 5.0(X11; Linux x86_64)AppleWebKit/537.36(GeckoのようなKHTML)Chrome/53.0.2785.101 Safari/537.36 Postmanトークン:8094b5ce-4b3d-cee7-2d10-f5dd2bc6b7b2アクセプト:/アクセプトエンコーディング:gzip、deflate Accept-Language:en -US、エン;身体とのQ = 0.8

ポスト:

POST/HTTP/1.1ホスト:127.0.0.1:15000接続:キープアライブのContent-Length:9ポストマン - トークン: 3fb2f5e0-2df1-5af4-7853-e9de84648dd5 Cache-Control:no-cache:chrome-extension:// fhbjgbiflinjbdggehcddcbncdddomop User-Agent:Mozilla/5.0(X11; Linux x86_64)AppleWebKit/537.36(GeckoのようなKHTML)Chrome/53.0 .2785.101 Safari/537.36コンテンツタイプ:テキスト/平野;のcharset = UTF-8受け入れ:/のAccept-エンコード:GZIPを、言語を受け入れ収縮:EN-US、EN; Q = 0.8

等...

パターンI書いては次のとおりです。

String somethingPattern = "(.*)?"; 

    String ipPattern = "(((2[0-4][0-9])|(25[0-5])|(1?[0-9]?[0-9]))\\.((2[0-4][0-9])|(25[0-5])|(1?[0-9]?[0-9]))\\.((2[0-4][0-9])|(25[0-5])|(1?[0-9]?[0-9]))\\.((2[0-4][0-9])|(25[0-5])|(1?[0-9]?[0-9]))|"+somethingPattern+")((:)\\d{3,})?"; // regex for ip varying from 0.0.0.0 to 255.255.255.255 or some string, followed or no by : and a port number 
    String objetoPattern = "([/?a-zA-Z0-9\\.\\-_]+)"; // regex for a linux path to a file, including only letters, numbers and -_. 

    String connectionPattern = "(connection:\\s*"+somethingPattern+")?"; 
    String contentLenPattern = "(content-length:\\s*([0-9]+))?"; 
    String postmanTokenPattern = "(postman-token:\\s*"+somethingPattern+")?"; 
    String cacheControlPattern = "(cache-control:\\s*"+somethingPattern+")?"; 
    String originPattern = "(origin:\\s*"+somethingPattern+")?"; 
    String userAgentPattern = "(user-agent:\\s*"+somethingPattern+")?"; 
    String charsetPattern = "(charset="+somethingPattern+")?"; 
    String contentTypePattern = "(content-type:\\s*"+somethingPattern+";"+charsetPattern+")?"; 
    String acceptPattern = "(accept:\\s*"+somethingPattern+")?"; 
    String acceptEncodingPattern = "(accept-encoding:\\s*"+somethingPattern+")?"; 
    String acceptLanguagePattern = "(accept-language:\\s*"+somethingPattern+")?"; 


    // (?i) is for the case of coming get, Get, GET... etc... 
    String pattern = "^(?i)(get|put|head|post|delete)\\s+?" + objetoPattern + "\\s+?HTTP/1.1\\s+?host:\\s+?" + ipPattern + "\\s+?" + connectionPattern + "\\s+?" + contentLenPattern + "\\s+?" + postmanTokenPattern + "\\s+?" + cacheControlPattern + "\\s+?" + originPattern + "\\s+?" + userAgentPattern + "\\s+?" + contentTypePattern + "\\s+?" + acceptPattern + "\\s+?" + acceptEncodingPattern + "\\s+?" + acceptLanguagePattern + "\\s+?$"; 

をGET一致し、から以外の要求のほとんどの罰金をグループ化された正規表現、HEAD本体なしのPOST。なぜこれが起こっているのか分かりません。私はorigin,content-lengthなどが要求に存在しない場合のように、各パターンの最後に?を置きます。しかし、これらのケースにマッチしていないにもかかわらず。マッチングのコードの一部である:

Pattern r = Pattern.compile(pattern); 
Matcher m = r.matcher(in); // this in is the input string that is the request all joined in a single line string 

if(m.find()){ 
// ...... 
} else { 
    System.out.println("Input didn't match"); 
} 

EDIT:ソケットからの入力を処理するコードの一部:

bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

     String in = ""; 
     while((msgDoSocket = bufferedReader.readLine()) != null){ 
      try { 
       in += msgDoSocket + " "; 
       if(msgDoSocket.isEmpty()){ 
        processaInput(in); // this calls the part that process regex 
       } 
      } catch (Exception ex) { 
       Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 

答えて

2

ヘッダー行は改行で区切られており、そしてヘッダーは2つの連続する改行で本文(存在する場合)から分離されます。 Scannerオブジェクトは、デフォルトでトークンを区切るために改行を使用するので、Matcherよりはるかに簡単です。単純にそれらの行を繰り返すことができます。これらの見出しを取得したら、ヘッダーキーの可能性をすべてカバーする百万種類の変数の代わりに、 ':'でスライスしてMapを作成できます。次に、あなたが送信したものと一致するように地図のキー値をチェックするだけです。

また、/Wiresharkを使用して、郵便番号による生のリクエストを確認することもできます。

This読者を使用して同じようにしてください。

+0

これでパターンマッチングで 'Scanner'オブジェクトを使用する方法は?私はScannerと 'BufferedReader'の両方を使って反復しましたが、どちらも最後の行として" Accept-Language:en-US、en; q = 0.8 "で終わりました。私はここでの問題は、入力要求メソッドを読み取るよりも正規表現のほうが重要だと思います – Fabiotk

関連する問題