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)
if err != nil {
fmt.Printf("STATUS CODE: %d %s\n", req.StatusCode(), req.StatusCode().Explicit())
panic(err)
}

View File

@ -1,6 +1,7 @@
package request
import (
"git.xdrm.io/gws/http/upgrade/response"
"git.xdrm.io/gws/internal/http/upgrade/request/parser/header"
"fmt"
"strconv"
@ -28,6 +29,7 @@ func (r *T) extractHostPort(bb header.HeaderValue) error {
// extract port
readPort, err := strconv.ParseUint(split[1], 10, 16)
if err != nil {
r.code = response.BAD_REQUEST
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 len(r.origin) > 0 {
err = r.checkOriginPolicy()
if err != nil {
err = r.checkOriginPolicy()
r.code = response.FORBIDDEN
return err
}
}
@ -50,6 +53,7 @@ func (r *T) extractHostPort(bb header.HeaderValue) error {
func (r *T) extractOrigin(bb header.HeaderValue) error {
if len(bb) != 1 {
r.code = response.FORBIDDEN
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 {
err := r.checkOriginPolicy()
if err != nil {
r.code = response.FORBIDDEN
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'")
}
@ -96,6 +102,7 @@ func (r *T) checkConnection(bb header.HeaderValue) error {
func (r *T) checkUpgrade(bb header.HeaderValue) error {
if len(bb) != 1 {
r.code = response.BAD_REQUEST
return fmt.Errorf("Upgrade header must have only 1 element")
}
@ -104,6 +111,7 @@ func (r *T) checkUpgrade(bb header.HeaderValue) error {
return nil
}
r.code = response.BAD_REQUEST
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 {
if len(bb) != 1 || string(bb[0]) != "13" {
r.code = response.UPGRADE_REQUIRED
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 {
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]))
}

View File

@ -1,6 +1,7 @@
package request
import (
"git.xdrm.io/gws/http/upgrade/response"
"fmt"
"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)
if err != nil {
r.code = response.BAD_REQUEST
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 */
head, err := header.Parse(b)
if err != nil {
r.code = response.BAD_REQUEST
return fmt.Errorf("Error parsing header: %s", err)
}

View File

@ -1,6 +1,7 @@
package request
import (
"git.xdrm.io/gws/http/upgrade/response"
"git.xdrm.io/gws/internal/http/reader"
"fmt"
"io"
@ -10,18 +11,19 @@ import (
// from a reader (typically bufio.NewRead of the socket)
func Build(r io.Reader) (request *T, err error) {
req := new(T)
req.code = 500
/* (1) Parse request
---------------------------------------------------------*/
/* (1) Get chunk reader */
cr := reader.NewReader(r)
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 */
req := new(T)
/* (3) Parse header line by line */
/* (2) Parse header line by line */
for {
line, err := cr.Read()
@ -30,21 +32,22 @@ func Build(r io.Reader) (request *T, err error) {
}
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)
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()
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)
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)
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
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
type T struct {
first bool // whether the first line has been read (GET uri HTTP/version)
// status code
code response.StatusCode
// request line
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
}