Browse Source

start of hpack package

Brad Fitzpatrick 11 years ago
parent
commit
b1b41787ff
3 changed files with 483 additions and 0 deletions
  1. 22 0
      hpack/hpack.go
  2. 112 0
      hpack/hpack_test.go
  3. 349 0
      hpack/tables.go

+ 22 - 0
hpack/hpack.go

@@ -0,0 +1,22 @@
+// Copyright 2014 The Go Authors.
+// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
+// Licensed under the same terms as Go itself:
+// https://code.google.com/p/go/source/browse/LICENSE
+
+// Package hpack implements HPACK, a compression format for
+// efficiently representing HTTP header fields in the context of HTTP/2.
+//
+// See http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08
+package hpack
+
+// A HeaderField is a name-value pair. Both the name and value are
+// treated as opaque sequences of octets.
+type HeaderField struct {
+	Name, Value string
+}
+
+// A Decoder is the decoding context for incremental processing of
+// header blocks.
+type Decoder struct {
+	// ...
+}

+ 112 - 0
hpack/hpack_test.go

@@ -0,0 +1,112 @@
+// Copyright 2014 The Go Authors.
+// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
+// Licensed under the same terms as Go itself:
+// https://code.google.com/p/go/source/browse/LICENSE
+
+package hpack
+
+import (
+	"bufio"
+	"regexp"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func TestStaticTable(t *testing.T) {
+	fromSpec := `
+          +-------+-----------------------------+---------------+
+          | 1     | :authority                  |               |
+          | 2     | :method                     | GET           |
+          | 3     | :method                     | POST          |
+          | 4     | :path                       | /             |
+          | 5     | :path                       | /index.html   |
+          | 6     | :scheme                     | http          |
+          | 7     | :scheme                     | https         |
+          | 8     | :status                     | 200           |
+          | 9     | :status                     | 204           |
+          | 10    | :status                     | 206           |
+          | 11    | :status                     | 304           |
+          | 12    | :status                     | 400           |
+          | 13    | :status                     | 404           |
+          | 14    | :status                     | 500           |
+          | 15    | accept-charset              |               |
+          | 16    | accept-encoding             | gzip, deflate |
+          | 17    | accept-language             |               |
+          | 18    | accept-ranges               |               |
+          | 19    | accept                      |               |
+          | 20    | access-control-allow-origin |               |
+          | 21    | age                         |               |
+          | 22    | allow                       |               |
+          | 23    | authorization               |               |
+          | 24    | cache-control               |               |
+          | 25    | content-disposition         |               |
+          | 26    | content-encoding            |               |
+          | 27    | content-language            |               |
+          | 28    | content-length              |               |
+          | 29    | content-location            |               |
+          | 30    | content-range               |               |
+          | 31    | content-type                |               |
+          | 32    | cookie                      |               |
+          | 33    | date                        |               |
+          | 34    | etag                        |               |
+          | 35    | expect                      |               |
+          | 36    | expires                     |               |
+          | 37    | from                        |               |
+          | 38    | host                        |               |
+          | 39    | if-match                    |               |
+          | 40    | if-modified-since           |               |
+          | 41    | if-none-match               |               |
+          | 42    | if-range                    |               |
+          | 43    | if-unmodified-since         |               |
+          | 44    | last-modified               |               |
+          | 45    | link                        |               |
+          | 46    | location                    |               |
+          | 47    | max-forwards                |               |
+          | 48    | proxy-authenticate          |               |
+          | 49    | proxy-authorization         |               |
+          | 50    | range                       |               |
+          | 51    | referer                     |               |
+          | 52    | refresh                     |               |
+          | 53    | retry-after                 |               |
+          | 54    | server                      |               |
+          | 55    | set-cookie                  |               |
+          | 56    | strict-transport-security   |               |
+          | 57    | transfer-encoding           |               |
+          | 58    | user-agent                  |               |
+          | 59    | vary                        |               |
+          | 60    | via                         |               |
+          | 61    | www-authenticate            |               |
+          +-------+-----------------------------+---------------+
+`
+	bs := bufio.NewScanner(strings.NewReader(fromSpec))
+	re := regexp.MustCompile(`\| (\d+)\s+\| (\S+)\s*\| (\S(.*\S)?)?\s+\|`)
+	for bs.Scan() {
+		l := bs.Text()
+		if !strings.Contains(l, "|") {
+			continue
+		}
+		m := re.FindStringSubmatch(l)
+		if m == nil {
+			continue
+		}
+		i, err := strconv.Atoi(m[1])
+		if err != nil {
+			t.Errorf("Bogus integer on line %q", l)
+			continue
+		}
+		if i < 1 || i > len(staticTable) {
+			t.Errorf("Bogus index %d on line %q", i, l)
+			continue
+		}
+		if got, want := staticTable[i-1].Name, m[2]; got != want {
+			t.Errorf("header index %d name = %q; want %q", i, got, want)
+		}
+		if got, want := staticTable[i-1].Value, m[3]; got != want {
+			t.Errorf("header index %d value = %q; want %q", i, got, want)
+		}
+	}
+	if err := bs.Err(); err != nil {
+		t.Error(err)
+	}
+}

+ 349 - 0
hpack/tables.go

@@ -0,0 +1,349 @@
+// Copyright 2014 The Go Authors.
+// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
+// Licensed under the same terms as Go itself:
+// https://code.google.com/p/go/source/browse/LICENSE
+
+package hpack
+
+// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
+var staticTable = []HeaderField{
+	{":authority", ""}, // index 1 (1-based)
+	{":method", "GET"},
+	{":method", "POST"},
+	{":path", "/"},
+	{":path", "/index.html"},
+	{":scheme", "http"},
+	{":scheme", "https"},
+	{":status", "200"},
+	{":status", "204"},
+	{":status", "206"},
+	{":status", "304"},
+	{":status", "400"},
+	{":status", "404"},
+	{":status", "500"},
+	{"accept-charset", ""},
+	{"accept-encoding", "gzip, deflate"},
+	{"accept-language", ""},
+	{"accept-ranges", ""},
+	{"accept", ""},
+	{"access-control-allow-origin", ""},
+	{"age", ""},
+	{"allow", ""},
+	{"authorization", ""},
+	{"cache-control", ""},
+	{"content-disposition", ""},
+	{"content-encoding", ""},
+	{"content-language", ""},
+	{"content-length", ""},
+	{"content-location", ""},
+	{"content-range", ""},
+	{"content-type", ""},
+	{"cookie", ""},
+	{"date", ""},
+	{"etag", ""},
+	{"expect", ""},
+	{"expires", ""},
+	{"from", ""},
+	{"host", ""},
+	{"if-match", ""},
+	{"if-modified-since", ""},
+	{"if-none-match", ""},
+	{"if-range", ""},
+	{"if-unmodified-since", ""},
+	{"last-modified", ""},
+	{"link", ""},
+	{"location", ""},
+	{"max-forwards", ""},
+	{"proxy-authenticate", ""},
+	{"proxy-authorization", ""},
+	{"range", ""},
+	{"referer", ""},
+	{"refresh", ""},
+	{"retry-after", ""},
+	{"server", ""},
+	{"set-cookie", ""},
+	{"strict-transport-security", ""},
+	{"transfer-encoding", ""},
+	{"user-agent", ""},
+	{"vary", ""},
+	{"via", ""},
+	{"www-authenticate", ""},
+}
+
+var huffmanCodes = []uint32{
+	0x1ff8,
+	0x7fffd8,
+	0xfffffe2,
+	0xfffffe3,
+	0xfffffe4,
+	0xfffffe5,
+	0xfffffe6,
+	0xfffffe7,
+	0xfffffe8,
+	0xffffea,
+	0x3ffffffc,
+	0xfffffe9,
+	0xfffffea,
+	0x3ffffffd,
+	0xfffffeb,
+	0xfffffec,
+	0xfffffed,
+	0xfffffee,
+	0xfffffef,
+	0xffffff0,
+	0xffffff1,
+	0xffffff2,
+	0x3ffffffe,
+	0xffffff3,
+	0xffffff4,
+	0xffffff5,
+	0xffffff6,
+	0xffffff7,
+	0xffffff8,
+	0xffffff9,
+	0xffffffa,
+	0xffffffb,
+	0x14,
+	0x3f8,
+	0x3f9,
+	0xffa,
+	0x1ff9,
+	0x15,
+	0xf8,
+	0x7fa,
+	0x3fa,
+	0x3fb,
+	0xf9,
+	0x7fb,
+	0xfa,
+	0x16,
+	0x17,
+	0x18,
+	0x0,
+	0x1,
+	0x2,
+	0x19,
+	0x1a,
+	0x1b,
+	0x1c,
+	0x1d,
+	0x1e,
+	0x1f,
+	0x5c,
+	0xfb,
+	0x7ffc,
+	0x20,
+	0xffb,
+	0x3fc,
+	0x1ffa,
+	0x21,
+	0x5d,
+	0x5e,
+	0x5f,
+	0x60,
+	0x61,
+	0x62,
+	0x63,
+	0x64,
+	0x65,
+	0x66,
+	0x67,
+	0x68,
+	0x69,
+	0x6a,
+	0x6b,
+	0x6c,
+	0x6d,
+	0x6e,
+	0x6f,
+	0x70,
+	0x71,
+	0x72,
+	0xfc,
+	0x73,
+	0xfd,
+	0x1ffb,
+	0x7fff0,
+	0x1ffc,
+	0x3ffc,
+	0x22,
+	0x7ffd,
+	0x3,
+	0x23,
+	0x4,
+	0x24,
+	0x5,
+	0x25,
+	0x26,
+	0x27,
+	0x6,
+	0x74,
+	0x75,
+	0x28,
+	0x29,
+	0x2a,
+	0x7,
+	0x2b,
+	0x76,
+	0x2c,
+	0x8,
+	0x9,
+	0x2d,
+	0x77,
+	0x78,
+	0x79,
+	0x7a,
+	0x7b,
+	0x7ffe,
+	0x7fc,
+	0x3ffd,
+	0x1ffd,
+	0xffffffc,
+	0xfffe6,
+	0x3fffd2,
+	0xfffe7,
+	0xfffe8,
+	0x3fffd3,
+	0x3fffd4,
+	0x3fffd5,
+	0x7fffd9,
+	0x3fffd6,
+	0x7fffda,
+	0x7fffdb,
+	0x7fffdc,
+	0x7fffdd,
+	0x7fffde,
+	0xffffeb,
+	0x7fffdf,
+	0xffffec,
+	0xffffed,
+	0x3fffd7,
+	0x7fffe0,
+	0xffffee,
+	0x7fffe1,
+	0x7fffe2,
+	0x7fffe3,
+	0x7fffe4,
+	0x1fffdc,
+	0x3fffd8,
+	0x7fffe5,
+	0x3fffd9,
+	0x7fffe6,
+	0x7fffe7,
+	0xffffef,
+	0x3fffda,
+	0x1fffdd,
+	0xfffe9,
+	0x3fffdb,
+	0x3fffdc,
+	0x7fffe8,
+	0x7fffe9,
+	0x1fffde,
+	0x7fffea,
+	0x3fffdd,
+	0x3fffde,
+	0xfffff0,
+	0x1fffdf,
+	0x3fffdf,
+	0x7fffeb,
+	0x7fffec,
+	0x1fffe0,
+	0x1fffe1,
+	0x3fffe0,
+	0x1fffe2,
+	0x7fffed,
+	0x3fffe1,
+	0x7fffee,
+	0x7fffef,
+	0xfffea,
+	0x3fffe2,
+	0x3fffe3,
+	0x3fffe4,
+	0x7ffff0,
+	0x3fffe5,
+	0x3fffe6,
+	0x7ffff1,
+	0x3ffffe0,
+	0x3ffffe1,
+	0xfffeb,
+	0x7fff1,
+	0x3fffe7,
+	0x7ffff2,
+	0x3fffe8,
+	0x1ffffec,
+	0x3ffffe2,
+	0x3ffffe3,
+	0x3ffffe4,
+	0x7ffffde,
+	0x7ffffdf,
+	0x3ffffe5,
+	0xfffff1,
+	0x1ffffed,
+	0x7fff2,
+	0x1fffe3,
+	0x3ffffe6,
+	0x7ffffe0,
+	0x7ffffe1,
+	0x3ffffe7,
+	0x7ffffe2,
+	0xfffff2,
+	0x1fffe4,
+	0x1fffe5,
+	0x3ffffe8,
+	0x3ffffe9,
+	0xffffffd,
+	0x7ffffe3,
+	0x7ffffe4,
+	0x7ffffe5,
+	0xfffec,
+	0xfffff3,
+	0xfffed,
+	0x1fffe6,
+	0x3fffe9,
+	0x1fffe7,
+	0x1fffe8,
+	0x7ffff3,
+	0x3fffea,
+	0x3fffeb,
+	0x1ffffee,
+	0x1ffffef,
+	0xfffff4,
+	0xfffff5,
+	0x3ffffea,
+	0x7ffff4,
+	0x3ffffeb,
+	0x7ffffe6,
+	0x3ffffec,
+	0x3ffffed,
+	0x7ffffe7,
+	0x7ffffe8,
+	0x7ffffe9,
+	0x7ffffea,
+	0x7ffffeb,
+	0xffffffe,
+	0x7ffffec,
+	0x7ffffed,
+	0x7ffffee,
+	0x7ffffef,
+	0x7fffff0,
+	0x3ffffee,
+}
+
+var huffmanCodeLen = []uint8{
+	13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28,
+	28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+	6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6,
+	5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10,
+	13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6,
+	15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5,
+	6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28,
+	20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23,
+	24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24,
+	22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23,
+	21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23,
+	26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25,
+	19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27,
+	20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23,
+	26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26,
+}