Skip to content

Commit 1760a73

Browse files
committedNov 1, 2020
Merge branch 'master' of github.com:pacedotdev/oto
2 parents 7fd213a + 875c675 commit 1760a73

File tree

11 files changed

+111
-13
lines changed

11 files changed

+111
-13
lines changed
 

‎README.md

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ These templates are already being used in production.
1414
* There are some [official Oto templates](https://github.com/pacedotdev/oto/tree/master/otohttp/templates)
1515
* The [Pace CLI tool](https://github.com/pacedotdev/pace/blob/master/oto/cli.go.plush) is generated from an open-source CLI template
1616

17+
## Learn
18+
19+
![](oto-video-preview.jpg)
20+
21+
* VIDEO: [Mat Ryer gives an overview of Oto at the Belfast Gophers meetup](https://www.youtube.com/watch?feature=youtu.be&v=DUg4ZITwMys)
22+
23+
* BLOG: [How code generation wrote our API and CLI](https://pace.dev/blog/2020/07/27/how-code-generation-wrote-our-api-and-cli.html)
24+
1725
## Tutorial
1826

1927
Install the project:

‎example/client.swift.plush

+30-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ class OtoClient {
1717
}
1818
<%= for (method) in service.Methods { %>
1919
<%= format_comment_text(method.Comment) %> func <%= camelize_down(method.Name) %>(withRequest <%= camelize_down(method.InputObject.TypeName) %>: <%= method.InputObject.TypeName %>, completion: @escaping (_ response: <%= method.OutputObject.TypeName %>?, _ error: Error?) -> ()) {
20-
var request = URLRequest(url: URL(string: "\(self.client.endpoint)/<%= service.Name %>.<%= method.Name %>")!)
20+
let url = "\(self.client.endpoint)/<%= service.Name %>.<%= method.Name %>"
21+
var request = URLRequest(url: URL(string: url)!)
2122
request.httpMethod = "POST"
2223
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
2324
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")
@@ -35,13 +36,27 @@ class OtoClient {
3536
completion(nil, err)
3637
return
3738
}
39+
if let httpResponse = response as? HTTPURLResponse {
40+
if (httpResponse.statusCode != 200) {
41+
let err = OtoError("\(url): \(httpResponse.statusCode) status code")
42+
completion(nil, err)
43+
return
44+
}
45+
}
3846
var <%= camelize_down(method.OutputObject.TypeName) %>: <%= method.OutputObject.TypeName %>
3947
do {
4048
<%= camelize_down(method.OutputObject.TypeName) %> = try JSONDecoder().decode(<%= method.OutputObject.TypeName %>.self, from: data!)
4149
} catch let err {
4250
completion(nil, err)
4351
return
4452
}
53+
if let serviceErr = <%= camelize_down(method.OutputObject.TypeName) %>.error {
54+
if (serviceErr != "") {
55+
let err = OtoError(serviceErr)
56+
completion(nil, err)
57+
return
58+
}
59+
}
4560
completion(<%= camelize_down(method.OutputObject.TypeName) %>, nil)
4661
}
4762
task.resume()
@@ -57,3 +72,17 @@ class OtoClient {
5772
<% } %>
5873
}
5974
<% } %>
75+
76+
struct OtoError: LocalizedError
77+
{
78+
var errorDescription: String? { return message }
79+
var failureReason: String? { return message }
80+
var recoverySuggestion: String? { return "" }
81+
var helpAnchor: String? { return "" }
82+
83+
private var message : String
84+
85+
init(_ description: String) {
86+
message = description
87+
}
88+
}

‎example/main.go

+11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"context"
55
"fmt"
6+
"io"
67
"log"
78
"net/http"
89

@@ -30,3 +31,13 @@ func main() {
3031
fmt.Println("listening at http://localhost:8080")
3132
log.Fatal(http.ListenAndServe(":8080", nil))
3233
}
34+
35+
// statusCodeHandler is useful for testing the server by returning a
36+
// specific HTTP status code.
37+
// http.Handle("/", statusCodeHandler(http.StatusInternalServerError))
38+
type statusCodeHandler int
39+
40+
func (c statusCodeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
41+
w.WriteHeader(int(c))
42+
io.WriteString(w, http.StatusText(int(c)))
43+
}

‎example/server.gen.go

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎example/server.go.plush

+3-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ package <%= def.PackageName %>
44

55
import (
66
"context"
7-
"log"
87
"net/http"
98

109
"github.com/pacedotdev/oto/otohttp"
@@ -16,7 +15,7 @@ import (
1615
<%= for (service) in def.Services { %>
1716
<%= format_comment_text(service.Comment) %>type <%= service.Name %> interface {
1817
<%= for (method) in service.Methods { %>
19-
<%= method.Name %>(context.Context, <%= method.InputObject.TypeName %>) (*<%= method.OutputObject.TypeName %>, error)<% } %>
18+
<%= format_comment_text(method.Comment) %><%= method.Name %>(context.Context, <%= method.InputObject.TypeName %>) (*<%= method.OutputObject.TypeName %>, error)<% } %>
2019
}
2120
<% } %>
2221

@@ -43,8 +42,7 @@ func (s *<%= camelize_down(service.Name) %>Server) handle<%= method.Name %>(w ht
4342
}
4443
response, err := s.<%= camelize_down(service.Name) %>.<%= method.Name %>(r.Context(), request)
4544
if err != nil {
46-
log.Println("TODO: oto service error:", err)
47-
http.Error(w, err.Error(), http.StatusInternalServerError)
45+
s.server.OnErr(w, r, err)
4846
return
4947
}
5048
if err := otohttp.Encode(w, r, http.StatusOK, response); err != nil {
@@ -57,7 +55,7 @@ func (s *<%= camelize_down(service.Name) %>Server) handle<%= method.Name %>(w ht
5755

5856
<%= for (object) in def.Objects { %>
5957
<%= format_comment_text(object.Comment) %>type <%= object.Name %> struct {
60-
<%= for (field) in object.Fields { %><%= format_comment_text(field.Comment) %><%= field.Name %> <%= if (field.Type.Multiple == true) { %>[]<% } %><%= field.Type.TypeName %> `json:"<%= camelize_down(field.Name) %><%= if (field.OmitEmpty) { %>,omitempty<% } %>"`
58+
<%= for (field) in object.Fields { %><%= format_comment_text(field.Comment) %><%= field.Name %> <%= if (field.Type.Multiple == true) { %>[]<% } %><%= field.Type.TypeName %> `json:"<%= field.NameLowerCamel %><%= if (field.OmitEmpty) { %>,omitempty<% } %>"`
6159
<% } %>
6260
}
6361
<% } %>

‎example/swift/SwiftCLIExample/SwiftCLIExample/client.gen.swift

+30-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ class GreeterService {
1919

2020
// Greet prepares a lovely greeting.
2121
func greet(withRequest greetRequest: GreetRequest, completion: @escaping (_ response: GreetResponse?, _ error: Error?) -> ()) {
22-
var request = URLRequest(url: URL(string: "\(self.client.endpoint)/GreeterService.Greet")!)
22+
let url = "\(self.client.endpoint)/GreeterService.Greet"
23+
var request = URLRequest(url: URL(string: url)!)
2324
request.httpMethod = "POST"
2425
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
2526
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")
@@ -37,13 +38,27 @@ class GreeterService {
3738
completion(nil, err)
3839
return
3940
}
41+
if let httpResponse = response as? HTTPURLResponse {
42+
if (httpResponse.statusCode != 200) {
43+
let err = OtoError("\(url): \(httpResponse.statusCode) status code")
44+
completion(nil, err)
45+
return
46+
}
47+
}
4048
var greetResponse: GreetResponse
4149
do {
4250
greetResponse = try JSONDecoder().decode(GreetResponse.self, from: data!)
4351
} catch let err {
4452
completion(nil, err)
4553
return
4654
}
55+
if let serviceErr = greetResponse.error {
56+
if (serviceErr != "") {
57+
let err = OtoError(serviceErr)
58+
completion(nil, err)
59+
return
60+
}
61+
}
4762
completion(greetResponse, nil)
4863
}
4964
task.resume()
@@ -72,3 +87,17 @@ struct GreetResponse: Encodable, Decodable {
7287

7388
}
7489

90+
91+
struct OtoError: LocalizedError
92+
{
93+
var errorDescription: String? { return message }
94+
var failureReason: String? { return message }
95+
var recoverySuggestion: String? { return "" }
96+
var helpAnchor: String? { return "" }
97+
98+
private var message : String
99+
100+
init(_ description: String) {
101+
message = description
102+
}
103+
}

‎example/swift/SwiftCLIExample/SwiftCLIExample/main.swift

-1
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,4 @@ greeterService.greet(withRequest: GreetRequest(
2020
print(response!.greeting!)
2121
}
2222

23-
print("hi")
2423
sleep(1)

‎oto-video-preview.jpg

20.4 KB
Loading

‎otohttp/templates/client.swift.plush

+23-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ class OtoClient {
1717
}
1818
<%= for (method) in service.Methods { %>
1919
<%= format_comment_text(method.Comment) %> func <%= camelize_down(method.Name) %>(withRequest <%= camelize_down(method.InputObject.TypeName) %>: <%= method.InputObject.TypeName %>, completion: @escaping (_ response: <%= method.OutputObject.TypeName %>?, _ error: Error?) -> ()) {
20-
var request = URLRequest(url: URL(string: "\(self.client.endpoint)/<%= service.Name %>.<%= method.Name %>")!)
20+
let url = "\(self.client.endpoint)/<%= service.Name %>.<%= method.Name %>"
21+
var request = URLRequest(url: URL(string: url)!)
2122
request.httpMethod = "POST"
2223
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
2324
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")
@@ -35,6 +36,13 @@ class OtoClient {
3536
completion(nil, err)
3637
return
3738
}
39+
if let httpResponse = response as? HTTPURLResponse {
40+
if (httpResponse.statusCode != 200) {
41+
let err = OtoError("\(url): \(httpResponse.statusCode) status code")
42+
completion(nil, err)
43+
return
44+
}
45+
}
3846
var <%= camelize_down(method.OutputObject.TypeName) %>: <%= method.OutputObject.TypeName %>
3947
do {
4048
<%= camelize_down(method.OutputObject.TypeName) %> = try JSONDecoder().decode(<%= method.OutputObject.TypeName %>.self, from: data!)
@@ -57,3 +65,17 @@ class OtoClient {
5765
<% } %>
5866
}
5967
<% } %>
68+
69+
struct OtoError: LocalizedError
70+
{
71+
var errorDescription: String? { return message }
72+
var failureReason: String? { return message }
73+
var recoverySuggestion: String? { return "" }
74+
var helpAnchor: String? { return "" }
75+
76+
private var message : String
77+
78+
init(_ description: String) {
79+
message = description
80+
}
81+
}

‎otohttp/templates/client.ts.plush

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ export class Client {
3535
headers: headers,
3636
body: JSON.stringify(<%= camelize_down(method.InputObject.TypeName) %>),
3737
})
38+
if (response.status !== 200) {
39+
throw new Error(`<%= service.Name %>.<%= method.Name %>: ${response.status} ${response.statusText}`);
40+
}
3841
return response.json().then((json) => {
3942
if (json.error) {
4043
throw new Error(json.error);

‎otohttp/templates/server.go.plush

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ package <%= def.PackageName %>
44

55
import (
66
"context"
7-
"log"
87
"net/http"
98

109
"github.com/pacedotdev/oto/otohttp"

0 commit comments

Comments
 (0)
Please sign in to comment.