[internal.http.request.parser.reqlin] Request-Line parse with minimum memory space
This commit is contained in:
parent
25879a3310
commit
00e5698391
|
@ -0,0 +1,73 @@
|
||||||
|
package reqline
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// extractHttpMethod extracts the HTTP method from a []byte
|
||||||
|
// and checks for errors
|
||||||
|
// allowed format: OPTIONS|GET|HEAD|POST|PUT|DELETE
|
||||||
|
func (r *T) extractHttpMethod(b []byte) error {
|
||||||
|
|
||||||
|
switch string(b) {
|
||||||
|
case "OPTIONS": r.method = OPTIONS
|
||||||
|
case "GET": r.method = GET
|
||||||
|
case "HEAD": r.method = HEAD
|
||||||
|
case "POST": r.method = POST
|
||||||
|
case "PUT": r.method = PUT
|
||||||
|
case "DELETE": r.method = DELETE
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Unknown HTTP method '%s'", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// extractURI extracts the URI from a []byte and checks for errors
|
||||||
|
// allowed format: /([^/]/)*/?
|
||||||
|
func (r *T) extractURI(b []byte) error {
|
||||||
|
|
||||||
|
/* (1) Check format */
|
||||||
|
checker := regexp.MustCompile("^(?:/[^/]+)*/?$")
|
||||||
|
if !checker.Match(b) {
|
||||||
|
return fmt.Errorf("Invalid URI format, expected an absolute path (starts with /), got '%s'", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (2) Store */
|
||||||
|
r.uri = string(b)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// extractHttpVersion extracts the version and checks for errors
|
||||||
|
// allowed format: [1-9] or [1.9].[0-9]
|
||||||
|
func (r *T) extractHttpVersion(b []byte) error {
|
||||||
|
|
||||||
|
/* (1) Extract version parts */
|
||||||
|
extractor := regexp.MustCompile(`^HTTP/([1-9])(?:\.([0-9]))?$`);
|
||||||
|
|
||||||
|
if !extractor.Match(b) {
|
||||||
|
return fmt.Errorf("Cannot parse HTTP version, expected INT or INT.INT, got '%s'", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (2) Extract version number */
|
||||||
|
matches := extractor.FindSubmatch(b)
|
||||||
|
var version byte = matches[1][0] - '0'
|
||||||
|
|
||||||
|
/* (3) Extract subversion (if exists) */
|
||||||
|
var subVersion byte = 0
|
||||||
|
if len(matches[2]) > 0 {
|
||||||
|
subVersion = matches[2][0] - '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (4) Store version (x 10 to fit uint8) */
|
||||||
|
r.version = version * 10 + subVersion
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package reqline
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// parseRequestLine parses the first HTTP request line
|
||||||
|
func (r *T) Parse(b []byte) error {
|
||||||
|
|
||||||
|
/* (1) Split by ' ' */
|
||||||
|
parts := bytes.Split(b, []byte(" "))
|
||||||
|
|
||||||
|
/* (2) Fail when missing parts */
|
||||||
|
if len(parts) != 3 {
|
||||||
|
return fmt.Errorf("Malformed Request-Line must have 3 space-separated elements, got %d", len(parts))
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (3) Extract HTTP method */
|
||||||
|
err := r.extractHttpMethod(parts[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (4) Extract URI */
|
||||||
|
err = r.extractURI(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (5) Extract version */
|
||||||
|
err = r.extractHttpVersion(parts[2])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("REQUEST-LINE\n------------\n - Method: '%d'\n - URI: '%s'\n - Version: %f\n", r.method, r.uri, float32(r.version)/10);
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package reqline
|
||||||
|
|
||||||
|
// httpMethod represents available http methods
|
||||||
|
type httpMethod byte
|
||||||
|
const (
|
||||||
|
OPTIONS httpMethod = iota
|
||||||
|
GET
|
||||||
|
HEAD
|
||||||
|
POST
|
||||||
|
PUT
|
||||||
|
DELETE
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// httpRequestLine represents the HTTP Request line
|
||||||
|
// defined in rfc-2616 : https://tools.ietf.org/html/rfc2616#section-5.1
|
||||||
|
type T struct {
|
||||||
|
method httpMethod
|
||||||
|
uri string
|
||||||
|
version byte
|
||||||
|
}
|
Loading…
Reference in New Issue