added request status code (defined in response) for creation from request to response

This commit is contained in:
xdrm-brackets 2018-04-25 18:09:26 +02:00
parent 08b73e87ad
commit d743448fce
7 changed files with 74 additions and 12 deletions

View File

@ -45,6 +45,7 @@ func manageClient(sock net.Conn) {
req, err := request.Build(sock) req, err := request.Build(sock)
if err != nil { if err != nil {
fmt.Printf("STATUS CODE: %d %s\n", req.StatusCode(), req.StatusCode().Explicit())
panic(err) panic(err)
} }

View File

@ -1,6 +1,7 @@
package request package request
import ( import (
"git.xdrm.io/gws/http/upgrade/response"
"git.xdrm.io/gws/internal/http/upgrade/request/parser/header" "git.xdrm.io/gws/internal/http/upgrade/request/parser/header"
"fmt" "fmt"
"strconv" "strconv"
@ -28,6 +29,7 @@ func (r *T) extractHostPort(bb header.HeaderValue) error {
// extract port // extract port
readPort, err := strconv.ParseUint(split[1], 10, 16) readPort, err := strconv.ParseUint(split[1], 10, 16)
if err != nil { if err != nil {
r.code = response.BAD_REQUEST
return fmt.Errorf("Cannot read port number '%s'", split[1]) return fmt.Errorf("Cannot read port number '%s'", split[1])
} }
@ -35,8 +37,9 @@ func (r *T) extractHostPort(bb header.HeaderValue) error {
// if 'Origin' header is already read, check it // if 'Origin' header is already read, check it
if len(r.origin) > 0 { if len(r.origin) > 0 {
err = r.checkOriginPolicy()
if err != nil { if err != nil {
err = r.checkOriginPolicy()
r.code = response.FORBIDDEN
return err return err
} }
} }
@ -50,6 +53,7 @@ func (r *T) extractHostPort(bb header.HeaderValue) error {
func (r *T) extractOrigin(bb header.HeaderValue) error { func (r *T) extractOrigin(bb header.HeaderValue) error {
if len(bb) != 1 { if len(bb) != 1 {
r.code = response.FORBIDDEN
return fmt.Errorf("Origin header must have a unique value") return fmt.Errorf("Origin header must have a unique value")
} }
@ -59,6 +63,7 @@ func (r *T) extractOrigin(bb header.HeaderValue) error {
if len(r.host) > 0 { if len(r.host) > 0 {
err := r.checkOriginPolicy() err := r.checkOriginPolicy()
if err != nil { if err != nil {
r.code = response.FORBIDDEN
return err return err
} }
} }
@ -87,6 +92,7 @@ func (r *T) checkConnection(bb header.HeaderValue) error {
} }
r.code = response.BAD_REQUEST
return fmt.Errorf("Connection header must be 'Upgrade'") return fmt.Errorf("Connection header must be 'Upgrade'")
} }
@ -96,6 +102,7 @@ func (r *T) checkConnection(bb header.HeaderValue) error {
func (r *T) checkUpgrade(bb header.HeaderValue) error { func (r *T) checkUpgrade(bb header.HeaderValue) error {
if len(bb) != 1 { if len(bb) != 1 {
r.code = response.BAD_REQUEST
return fmt.Errorf("Upgrade header must have only 1 element") return fmt.Errorf("Upgrade header must have only 1 element")
} }
@ -104,6 +111,7 @@ func (r *T) checkUpgrade(bb header.HeaderValue) error {
return nil return nil
} }
r.code = response.BAD_REQUEST
return fmt.Errorf("Upgrade header must be 'websocket', got '%s'", bb[0]) return fmt.Errorf("Upgrade header must be 'websocket', got '%s'", bb[0])
} }
@ -113,6 +121,7 @@ func (r *T) checkUpgrade(bb header.HeaderValue) error {
func (r *T) checkVersion(bb header.HeaderValue) error { func (r *T) checkVersion(bb header.HeaderValue) error {
if len(bb) != 1 || string(bb[0]) != "13" { if len(bb) != 1 || string(bb[0]) != "13" {
r.code = response.UPGRADE_REQUIRED
return fmt.Errorf("Sec-WebSocket-Version header must be '13'") return fmt.Errorf("Sec-WebSocket-Version header must be '13'")
} }
@ -126,6 +135,7 @@ func (r *T) checkVersion(bb header.HeaderValue) error {
func (r *T) extractKey(bb header.HeaderValue) error { func (r *T) extractKey(bb header.HeaderValue) error {
if len(bb) != 1 || len(bb[0]) != 24 { if len(bb) != 1 || len(bb[0]) != 24 {
r.code = response.BAD_REQUEST
return fmt.Errorf("Sec-WebSocket-Key header must be a unique 24 bytes base64 value, got %d bytes", len(bb[0])) return fmt.Errorf("Sec-WebSocket-Key header must be a unique 24 bytes base64 value, got %d bytes", len(bb[0]))
} }

View File

@ -1,6 +1,7 @@
package request package request
import ( import (
"git.xdrm.io/gws/http/upgrade/response"
"fmt" "fmt"
"git.xdrm.io/gws/internal/http/upgrade/request/parser/header" "git.xdrm.io/gws/internal/http/upgrade/request/parser/header"
) )
@ -17,6 +18,7 @@ func (r *T) parseHeader(b []byte) error {
err := r.request.Parse(b) err := r.request.Parse(b)
if err != nil { if err != nil {
r.code = response.BAD_REQUEST
return fmt.Errorf("Error while parsing first line: %s", err) return fmt.Errorf("Error while parsing first line: %s", err)
} }
@ -32,6 +34,7 @@ func (r *T) parseHeader(b []byte) error {
/* (1) Try to parse header */ /* (1) Try to parse header */
head, err := header.Parse(b) head, err := header.Parse(b)
if err != nil { if err != nil {
r.code = response.BAD_REQUEST
return fmt.Errorf("Error parsing header: %s", err) return fmt.Errorf("Error parsing header: %s", err)
} }

View File

@ -1,6 +1,7 @@
package request package request
import ( import (
"git.xdrm.io/gws/http/upgrade/response"
"git.xdrm.io/gws/internal/http/reader" "git.xdrm.io/gws/internal/http/reader"
"fmt" "fmt"
"io" "io"
@ -10,18 +11,19 @@ import (
// from a reader (typically bufio.NewRead of the socket) // from a reader (typically bufio.NewRead of the socket)
func Build(r io.Reader) (request *T, err error) { func Build(r io.Reader) (request *T, err error) {
req := new(T)
req.code = 500
/* (1) Parse request /* (1) Parse request
---------------------------------------------------------*/ ---------------------------------------------------------*/
/* (1) Get chunk reader */ /* (1) Get chunk reader */
cr := reader.NewReader(r) cr := reader.NewReader(r)
if err != nil { if err != nil {
return nil, fmt.Errorf("Error while creating chunk reader: %s", err) return req, fmt.Errorf("Error while creating chunk reader: %s", err)
} }
/* (2) Init request */ /* (2) Parse header line by line */
req := new(T)
/* (3) Parse header line by line */
for { for {
line, err := cr.Read() line, err := cr.Read()
@ -30,21 +32,22 @@ func Build(r io.Reader) (request *T, err error) {
} }
if err != nil { if err != nil {
return nil, fmt.Errorf("Cannot read from reader: %s", err) return req, fmt.Errorf("Cannot read from reader: %s", err)
} }
err = req.parseHeader(line) err = req.parseHeader(line)
if err != nil { if err != nil {
return nil, fmt.Errorf("Parsing error: %s\n", err); return req, fmt.Errorf("Parsing error: %s\n", err);
} }
} }
/* (4) Check completion */ /* (3) Check completion */
err = req.isComplete() err = req.isComplete()
if err != nil { if err != nil {
return nil, err req.code = response.BAD_REQUEST
return req, err
} }
@ -60,7 +63,14 @@ func (r T) String() string{
l1 := fmt.Sprintf("Upgrade Request\n - host: %s\n - port: %d\n - origin: %s\n", r.host, r.port, r.origin) l1 := fmt.Sprintf("Upgrade Request\n - host: %s\n - port: %d\n - origin: %s\n", r.host, r.port, r.origin)
l2 := fmt.Sprintf(" - origin policy: %t\n - connection header: %t\n - upgrade header: %t\n - valid ws version: %t\n", r.validPolicy, r.hasConnection, r.hasUpgrade, r.hasVersion) l2 := fmt.Sprintf(" - origin policy: %t\n - connection header: %t\n - upgrade header: %t\n - valid ws version: %t\n", r.validPolicy, r.hasConnection, r.hasUpgrade, r.hasVersion)
l3 := fmt.Sprintf(" - key: %s\n - protocols: %s\n", r.key, r.protocols) l3 := fmt.Sprintf(" - key: %s\n - protocols: %s\n", r.key, r.protocols)
l4 := fmt.Sprintf(" - current status: %d %s\n", r.code, r.code.Explicit())
return fmt.Sprintf("%s%s%s", l1, l2, l3) return fmt.Sprintf("%s%s%s%s", l1, l2, l3, l4)
} }
// StatusCode returns the status current
func (r T) StatusCode() response.StatusCode {
return r.code
}

View File

@ -1,11 +1,15 @@
package request package request
import "git.xdrm.io/gws/internal/http/upgrade/request/parser/reqline" import "git.xdrm.io/gws/internal/http/upgrade/request/parser/reqline"
import "git.xdrm.io/gws/http/upgrade/response"
// T represents an HTTP Upgrade request // T represents an HTTP Upgrade request
type T struct { type T struct {
first bool // whether the first line has been read (GET uri HTTP/version) first bool // whether the first line has been read (GET uri HTTP/version)
// status code
code response.StatusCode
// request line // request line
request reqline.T request reqline.T

View File

@ -0,0 +1,25 @@
package response
// StatusCode maps the status codes (and description)
type StatusCode uint16
var SWITCHING_PROTOCOLS StatusCode = 101 // handshake success
var BAD_REQUEST StatusCode = 400 // missing/malformed headers
var FORBIDDEN StatusCode = 403 // invalid origin policy, TLS required
var UPGRADE_REQUIRED StatusCode = 426 // invalid WS version
var NOT_FOUND StatusCode = 404 // unserved or invalid URI
var INTERNAL StatusCode = 500 // custom error
func (sc StatusCode) Explicit() string {
switch sc {
case SWITCHING_PROTOCOLS: return "Switching Protocols"
case BAD_REQUEST: return "Bad Request"
case FORBIDDEN: return "Forbidden"
case UPGRADE_REQUIRED: return "Upgrade Required"
case NOT_FOUND: return "Not Found"
case INTERNAL: return "Internal Server Error"
default:
return "Unknown Status Code"
}
}

View File

@ -0,0 +1,9 @@
package response
// T represents an HTTP Upgrade Response
type T struct {
code StatusCode // status code
accept []byte // processed from Sec-WebSocket-Key
protocol []byte // set from Sec-WebSocket-Protocol or none if not received
}