Skip to content

Commit

Permalink
Merge pull request #253 from Syuparn/add-server
Browse files Browse the repository at this point in the history
props: add server
  • Loading branch information
Syuparn authored Jun 13, 2023
2 parents f515ac8 + 8966977 commit 44085e8
Show file tree
Hide file tree
Showing 18 changed files with 2,006 additions and 81 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ jobs:
- name: Check out code into the Go module directory
uses: actions/checkout@v2

- name: Generate source files
run: go generate

- name: Build
run: go build

Expand Down
422 changes: 422 additions & 0 deletions CREDITS

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions example/server.pangaea
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
invite!("http")

# CAUTION: You should use external DB to update data because all Pangaea objects are immutable and stateless!
# (this is just a dummy dataset which cannot be updated)
users := [
{id: "1", name: "Taro"},
{id: "2", name: "Jiro"},
{id: "3", name: "Hanako"},
]

Server.serve(
S.post("users") {|req| Response.new(status: 201, body: {id: "12345", name: req.body.decJSON.name}.S)},
S.get("users") {|req| {users: users}},
S.get("users/:id") {|req| users.find {.id == req.params.id} || Response.new(status: 404, body: {msg: "User not found"}.S)},
S.delete("users/:id") {|req| Response.new(status: 204)},
)

# try curl to request to the server
# curl localhost:8080/users
# curl localhost:8080/users/3
# curl -XDELETE localhost:8080/users/3
# curl -XPOST localhost:8080/users -d '{"name": "Taro"}' -H 'Content-Type: application/json'
15 changes: 14 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,23 @@ go 1.20
require (
github.com/Songmu/gocredits v0.3.0
github.com/dlclark/regexp2 v1.4.0
github.com/labstack/echo/v4 v4.10.2
github.com/lithammer/dedent v1.1.0
github.com/macrat/simplexer v0.0.0-20180110131648-bce8e0661570
github.com/tanaton/dtoa v0.0.0-20190918101016-f12936c87cdb
golang.org/x/tools v0.1.0
golang.org/x/tools v0.1.12
)

require (
github.com/labstack/gommon v0.4.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
)

// bundle to patch lexer
Expand Down
65 changes: 42 additions & 23 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,31 +1,50 @@
github.com/Songmu/gocredits v0.3.0 h1:BOredmhBQhrZjanpQpTWVl7aCuQW83Sea85kA0E9lOs=
github.com/Songmu/gocredits v0.3.0/go.mod h1:GGUAT/3BmUVgvfHxm07agU6Zz+ZSeGg5gvqN6N/CxH0=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/tanaton/dtoa v0.0.0-20190918101016-f12936c87cdb h1:il95NPTEHqAkHbZfBCzEKJdwJJ4xwdpk/s0IsZWYr/4=
github.com/tanaton/dtoa v0.0.0-20190918101016-f12936c87cdb/go.mod h1:NJ73Q9luv5I1cYrIYSfGC7+oHggSb4YpjpaPGDTHmxI=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
3 changes: 3 additions & 0 deletions manual_tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# manual tests

This directory contains tests that cannot be runned on GitHub Actions.
43 changes: 43 additions & 0 deletions manual_tests/http_test.pangaea
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
invite!("http")

down := S.serve(
S.get("/hello") {"world"},
S.post("/users") {|req| {id: 1, name: req.body.decJSON.name}},
S.put("/users/:id") {|req| {id: req.params.id, name: "John"}},
S.delete("/users/:id") {|req| Response.new(status: 204)},
S.patch("/users") {|req| "ok"},
background: true,
url: ":50000",
)
defer down()

res := C.get("http://localhost:50000/hello")
assertEq(res.status, 200)
assertEq(res.body, "world")

res := C.post("http://localhost:50000/users", body: `{"name": "Taro"}`)
assertEq(res.status, 200)
assertEq(res.body, `{"id": 1, "name": "Taro"}`)
assertEq(res.header("Content-Type"), "application/json; charset=UTF-8")

res := C.put("http://localhost:50000/users/12345")
assertEq(res.status, 200)
assertEq(res.body, `{"id": "12345", "name": "John"}`)

res := C.delete("http://localhost:50000/users/56789")
assertEq(res.status, 204)

res := C.patch("http://localhost:50000/users")
assertEq(res.status, 200)
assertEq(res.body, `ok`)

# default port
down2 := S.serve(
S.get("/hello2") {"world2"},
background: true,
)
defer down2()

res := C.get("http://localhost:8080/hello2")
assertEq(res.status, 200)
assertEq(res.body, "world2")
57 changes: 42 additions & 15 deletions native/modules/http.pangaea
Original file line number Diff line number Diff line change
@@ -1,24 +1,51 @@
_internal := import("http/internal")

Response := {
new: _init('status, 'body, 'headers),
new: m{|status: 200, body: "", headers: {}| .bear({status: status, body: body, headers: headers})},
header: m{|key| .headers[key][0]},
}

Client := {
get: m{|url, headers: {}, queries: {}|
_internal['request](method: 'GET, url: url, headers: headers, queries: queries).{self._toResponse(\)}
},
post: m{|url, headers: {}, body: ""|
_internal['request](method: 'POST, url: url, headers: headers, body: body).{self._toResponse(\)}
},
put: m{|url, headers: {}, body: ""|
_internal['request](method: 'PUT, url: url, headers: headers, body: body).{self._toResponse(\)}
},
delete: m{|url, headers: {}, queries: {}|
_internal['request](method: 'DELETE, url: url, headers: headers, queries: queries).{self._toResponse(\)}
_toResponse: m{|r| Response.new(status: r.status, body: r.body, headers: r.headers)},
**(['post, 'put, 'patch]@({}){|name|
[name, m{|url, headers: {}, body: ""|
_internal['request](method: name.uc, url: url, headers: headers, body: body).{self._toResponse(\)}
}]
}),
**(['get, 'delete]@({}){|name|
[name, m{|url, headers: {}, queries: {}|
_internal['request](method: name.uc, url: url, headers: headers, queries: queries).{self._toResponse(\)}
}]
}),
}

# alias
C := Client

Server := {
serve: m{|background: false, url: ":8080"|
handlers := \0[1:]
_internal['newServer](*handlers).{|srv|
return _internal['serve](srv, url) if !background
_internal['serveBackground](srv, url)
{_internal['stop](srv)} # return stop function
}
},
patch: m{|url, headers: {}, body: ""|
_internal['request](method: 'PATCH, url: url, headers: headers, body: body).{self._toResponse(\)}
_wrapCallback: m{|f|
{|req|
f(req).{|res|
return res if res.proto == Response
return {body: res} if res.proto == Str
{body: res.S, _isJSON: true}
}
}
},
_toResponse: m{|r| Response.new(r.status, r.body, r.headers)},
**(['get, 'post, 'put, 'delete, 'patch]@({}){|name|
[name, m{|url, callback|
_internal['newHandler](name.uc, url, ._wrapCallback(callback))
}]
}),
}

# alias
S := Server
Loading

0 comments on commit 44085e8

Please sign in to comment.