added request status code (defined in response) for creation from request to response
This commit is contained in:
parent
08b73e87ad
commit
d743448fce
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue