-
Notifications
You must be signed in to change notification settings - Fork 1
/
types.go
148 lines (124 loc) · 4.55 KB
/
types.go
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2015 Luke Shumaker
// Package httpentity provides a "framework" for exposing resources
// over HTTP.
//
// Within the framework, an "Entity" is simply something that can be
// accessed over HTTP. A "NetEntity" is something that is capable of
// being transmitted as an HTTP body--most Entities will also be
// NetEntities. But, things like error messages are NetEntities, but
// aren't Entities, as it's not a normal thing that you can request.
//
// An Entity is accessed using the method allowed in
// (*Entity).Methods(). An entity may also have children--these are
// accessed with (*Entity).Subentities(childName, request).
//
// A Router is the entire Entity tree; it mostly just takes the root
// Entity of the tree. It handles dispatching Requests to the correct
// Entity, then formatting the Responses to the output stream.
package httpentity
import (
"io"
"locale"
"net/http"
"net/url"
)
type Logger interface {
Printf(format string, v ...interface{})
Println(v ...interface{})
}
////////////////////////////////////////////////////////////////////////////////
// A Router represents the root of an Entity tree, and handles reading
// and writing messages to the network socket.
type Router struct {
Prefix string
Root RootEntity
Decoders map[string]func(io.Reader, map[string]string) (interface{}, locale.Error)
Middlewares []Middleware
// Whether to include stacktraces in HTTP 500 responses
Stacktrace bool
Log Logger
// Whether to trust `X-Forwarded-Scheme:` and RFC 7239
// `Forwarded: proto=`
TrustForwarded bool
MethodNotAllowed func(entity Entity, request Request) Response
outsideHandler func(Request) Response
insideHandler func(Request, Entity) Response
}
////////////////////////////////////////////////////////////////////////////////
// Request is an incoming HTTP request to be handled.
type Request struct {
Method string
URL *url.URL
Headers http.Header
Entity interface{}
Things map[string]interface{} // Objects added by middlewares
cookies map[string]*http.Cookie // cached
}
// The Response to an HTTP request.
type Response struct {
Status int16
Headers http.Header
Entity NetEntity
InhibitNotAcceptable bool
InhibitMultipleChoices bool
encoder Encoder
}
// An Entity is some resource that is accessible over HTTP.
type Entity interface {
// Methods() returns a map of HTTP request methods to Handlers
// that handle requests for this Entity.
Methods() map[string]func(Request) Response
}
// An EntityGroup is an Entity that also has child entities (i.e., a
// directory or folder).
type EntityGroup interface {
Entity
// Subentity(name, request) returns the child of this entity
// with the name `name`, or nil if a child with that name
// doesn't exist.
//
// The Request is included in the function call so that it can
// be determined if the user has permission to access that
// child.
Subentity(name string, request Request) Entity
// SubentityNotFound is called if Subentity returns nil. If
// the name contains a slash; it indicates that the child was
// found, but a grandchild was requested, and the child wasn't
// an EntityGroup.
SubentityNotFound(name string, request Request) Response
}
// EntityExtra is an Entity that provides a custom HTTP 405 ("Method
// Not Allowed") handler.
type EntityExtra interface {
Entity
MethodNotAllowed(request Request) Response
}
// RootEntity is the union of EntityGroup and EntityExtra.
type RootEntity interface {
Entity
Subentity(name string, request Request) Entity
SubentityNotFound(name string, request Request) Response
MethodNotAllowed(request Request) Response
}
////////////////////////////////////////////////////////////////////////////////
type Encoder interface {
Locales() []locale.Spec
Write(io.Writer, locale.Spec) locale.Error
IsText() bool
}
// A NetEntity is just something that is capable of being transmitted
// over the network (in a variety of formats).
type NetEntity interface {
// Encoders() returns a map of MIME-types to encoders that
// serialize the NetEntity to that type.
Encoders() map[string]Encoder
}
////////////////////////////////////////////////////////////////////////////////
// A Middleware is something that wraps the request handler.
type Middleware struct {
// Outside is able to affect the entity that is looked up
Outside func(Request, func(Request) Response) Response
// Inside cannot affect the entity that is looked up, but it
// gets to inspect the entity.
Inside func(Request, Entity, func(Request, Entity) Response) Response
}