-
Notifications
You must be signed in to change notification settings - Fork 0
/
doc.go
144 lines (109 loc) Β· 5.04 KB
/
doc.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
//
// Copyright (C) 2019 Dmitry Kolesnikov
//
// This file may be modified and distributed under the terms
// of the MIT license. See the LICENSE file for details.
// https://github.com/fogfish/gurl
//
/*
Package gurl is a class of High Order Component which can do http requests
with few interesting property such as composition and laziness. The library
implements rough and naive Haskell's equivalent of do-notation, so called
monadic binding form. This construction decorates http i/o pipeline(s) with
"programmable commas".
Inspiration
Microservices have become a design style to evolve system architecture
in parallel, implement stable and consistent interfaces. An expressive
language is required to design the variety of network communication use-cases.
A pure functional languages fits very well to express communication behavior.
The language gives a rich techniques to hide the networking complexity using
monads as abstraction. The IO-monads helps us to compose a chain of network
operations and represent them as pure computation, build a new things from
small reusable elements. The library is implemented after Erlang's
https://github.com/fogfish/m_http
The library attempts to adapts a human-friendly syntax of HTTP request/response
logging/definition used by curl with Behavior as a Code paradigm. It tries to
connect cause-and-effect (Given/When/Then) with the networking (Input/Process/Output).
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/7.54.0
> Accept: application/json
>
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Server: ECS (phd/FD58)
< ...
This semantic provides an intuitive approach to specify HTTP requests/responses.
Adoption of this syntax as Go native code provides a rich capability to network
programming.
Key features
β£ cause-and-effect abstraction of HTTP request/response, naive do-notation
β£ high-order composition of individual HTTP requests to complex networking computations
β£ human-friendly, Go native and declarative syntax to depict HTTP operations
β£ implements a declarative approach for testing of RESTful interfaces
β£ automatically encodes/decodes Go native HTTP payload using Content-Type hints
β£ supports generic transformation to algebraic data types
β£ simplify error handling with naive Either implementation
IO Category
Standard Golang packages implements low-level HTTP interface, which
requires knowledge about protocol itself, aspects of Golang implementation,
a bit of boilerplate coding and lack of standardized chaining (composition)
of individual requests.
gurl library inherits an ability of pure functional languages to express
communication behavior by hiding the networking complexity using category pattern
(aka "do"-notation). This pattern helps us to compose a chain of network operations
and represent them as pure computation, build a new things from small reusable
elements. This library uses the "do"-notation, so called monadic binding form.
It is well know in functional programming languages such as Haskell and
Scala. The networking becomes a collection of composed "do"-notation in context
of a state monad.
A composition of HTTP primitives within the category are written with the following
syntax.
gurl.Join(arrows ...Arrow) Arrow
Here, each arrow is a morphism applied to HTTP protocol. The implementation defines
an abstraction of the protocol environments and lenses to focus inside it. In other
words, the category represents the environment as an "invisible" side-effect of
the composition.
`gurl.Join(arrows ...Arrow) Arrow` and its composition implements lazy I/O. It only
returns a "promise", you have to evaluate it in the context of IO instance.
io := gurl.IO()
fn := gurl.Join( ... )
fn(io)
Basics
The following code snippet demonstrates a typical usage scenario.
import (
"github.com/fogfish/gurl"
"github.com/fogfish/gurl/http"
Ζ "github.com/fogfish/gurl/http/recv"
ΓΈ "github.com/fogfish/gurl/http/send"
)
// You can declare any types and use them as part of networking I/O.
type Payload struct {
Origin string `json:"origin"`
Url string `json:"url"`
}
var data Payload
var lazy := http.Join(
// declares HTTP method and destination URL
ΓΈ.GET.URL("http://httpbin.org/get"),
// HTTP content negotiation, declares acceptable types
ΓΈ.Accept.JSON,
// requires HTTP Status Code to be 200 OK
Ζ.Status.OK,
// requites HTTP Header to be Content-Type: application/json
Ζ.ContentType.JSON,
// unmarshal JSON to the variable
Ζ.Recv(&data),
)
// Note: http do not hold yet, a results of HTTP I/O
// it is just a composable "promise", you have to
// evaluate a side-effect of HTTP "computation"
if lazy(gurl.IO( ... )).Fail != nil {
// error handling
}
The evaluation of "program" fails if either networking fails or expectations
do not match actual response. There are no needs to check error code after
each operation. The composition is smart enough to terminate "program" execution.
See User Guide about the library at https://github.com/fogfish/gurl
*/
package gurl