X-Git-Url: http://nitlanguage.org diff --git a/lib/nitcorn/http_request.nit b/lib/nitcorn/http_request.nit index 6431ace..1833fca 100644 --- a/lib/nitcorn/http_request.nit +++ b/lib/nitcorn/http_request.nit @@ -3,6 +3,7 @@ # Copyright 2013 Frederic Sevillano # Copyright 2013 Jean-Philippe Caissy # Copyright 2014 Alexis Laferrière +# Copyright 2014 Alexandre Terrasa # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,11 +20,11 @@ # Provides the `HttpRequest` class and services to create it module http_request -import standard +import core # A request received over HTTP, is build by `HttpRequestParser` class HttpRequest - private init do end + private init is old_style_init do end # HTTP protocol version var http_version: String @@ -46,6 +47,9 @@ class HttpRequest # The header of this request var header = new HashMap[String, String] + # The raw body of the request. + var body = "" + # The content of the cookie of this request var cookie = new HashMap[String, String] @@ -54,6 +58,44 @@ class HttpRequest # The arguments passed with the POST method var post_args = new HashMap[String, String] + + # The arguments passed with the POST or GET method (with a priority on POST) + var all_args = new HashMap[String, String] + + # Returns argument `arg_name` in the request as a String + # or null if it was not found. + # Also cleans the String by trimming it. + # If the Strings happens to be empty after trimming, + # the method will return `null` + # + # NOTE: Prioritizes POST before GET + fun string_arg(arg_name: String): nullable String do + if not all_args.has_key(arg_name) then return null + var s = all_args[arg_name].trim + if s.is_empty then return null + return s + end + + # Returns argument `arg_name` as an Int or `null` if not found or not a number. + # + # NOTE: Prioritizes POST before GET + fun int_arg(arg_name: String): nullable Int do + if not all_args.has_key(arg_name) then return null + var i = all_args[arg_name] + if not i.is_numeric then return null + return i.to_i + end + + # Returns argument `arg_name` as a Bool or `null` if not found or not a boolean. + # + # NOTE: Prioritizes POST before GET + fun bool_arg(arg_name: String): nullable Bool do + if not all_args.has_key(arg_name) then return null + var i = all_args[arg_name] + if i == "true" then return true + if i == "false" then return false + return null + end end # Utility class to parse a request string and build a `HttpRequest` @@ -61,7 +103,7 @@ end # The main method is `parse_http_request`. class HttpRequestParser # The current `HttpRequest` under construction - private var http_request: HttpRequest + private var http_request: HttpRequest is noinit # Untreated body private var body = "" @@ -72,8 +114,7 @@ class HttpRequestParser # Words of the first line private var first_line = new Array[String] - init do end - + # Parse the `first_line`, `header_fields` and `body` of `full_request`. fun parse_http_request(full_request: String): nullable HttpRequest do clear_data @@ -84,6 +125,10 @@ class HttpRequestParser segment_http_request(full_request) # Parse first line, looks like "GET dir/index.html?user=xymus HTTP/1.0" + if first_line.length < 3 then + print "HTTP error: request first line apprears invalid: {first_line}" + return null + end http_request.method = first_line[0] http_request.url = first_line[1] http_request.http_version = first_line[2] @@ -92,23 +137,24 @@ class HttpRequestParser if http_request.url.has('?') then http_request.uri = first_line[1].substring(0, first_line[1].index_of('?')) http_request.query_string = first_line[1].substring_from(first_line[1].index_of('?')+1) + + var parse_url = parse_url http_request.get_args = parse_url + http_request.all_args.add_all parse_url else http_request.uri = first_line[1] end # POST args if http_request.method == "POST" then + http_request.body = body var lines = body.split_with('&') - for line in lines do + for line in lines do if not line.trim.is_empty then var parts = line.split_once_on('=') if parts.length > 1 then var decoded = parts[1].replace('+', " ").from_percent_encoding - if decoded == null then - print "decode error" - continue - end http_request.post_args[parts[0]] = decoded + http_request.all_args[parts[0]] = decoded else print "POST Error: {line} format error on {line}" end