aboutsummaryrefslogtreecommitdiff
path: root/app/request.go
blob: 8dd161b96e8a27464b8aa75218a32200e7e971a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package main

import (
	"bufio"
	"bytes"
	"fmt"
)

type requestHeaders struct {
	headers map[string]string
}

type requestLine struct {
	method  string
	target  string
	version string
}

type Request struct {
	line    requestLine
	headers requestHeaders
}

func newRequestHeaders(reader *bufio.Reader) (requestHeaders, error) {
	request := requestHeaders{make(map[string]string)}

	for {
		buf, err := reader.ReadBytes('\n')
		if err != nil {
			return request, err
		}

		if bytes.Equal(buf, []byte{'\r', '\n'}) {
			return request, nil
		}

		buf = bytes.TrimSuffix(buf, []byte{'\r', '\n'})
		header := bytes.Split(buf, []byte{':', ' '})

		if len(header) != 2 {
			return request, fmt.Errorf("invalid header line")
		}

		request.headers[string(header[0])] = string(header[1])
	}
}

func newRequestLine(reader *bufio.Reader) (requestLine, error) {
	buf, err := reader.ReadBytes('\n')
	if err != nil {
		return requestLine{}, err
	}

	buf = bytes.TrimSuffix(buf, []byte{'\r', '\n'})
	elements := bytes.Split(buf, []byte{' '})

	if len(elements) != 3 {
		return requestLine{}, fmt.Errorf("invalid request, expected 3 elements, got %d", len(elements))
	}

	return requestLine{string(elements[0]), string(elements[1]), string(elements[2])}, nil
}

func NewRequest(reader *bufio.Reader) (*Request, error) {
	line, err := newRequestLine(reader)
	if err != nil {
		return nil, err
	}

	headers, err := newRequestHeaders(reader)
	if err != nil {
		return nil, err
	}

	return &Request{line, headers}, nil
}

func (r *Request) Method() string {
	return r.line.method
}

func (r *Request) Target() string {
	return r.line.target
}

func (r *Request) Header(name string) string {
	return r.headers.headers[name]
}