Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose WriteMessage for middleware to return proto message #9

Merged
merged 11 commits into from
Oct 22, 2017

Conversation

sunfmin
Copy link
Contributor

@sunfmin sunfmin commented Oct 13, 2017

No description provided.

@sunfmin sunfmin requested a review from bodhi October 13, 2017 07:45
prottp.go Outdated
var err error
isJSON := isRequestJSON(r)
if isJSON && w.Header().Get("Content-Type") == "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're changing this, how about updating the headers:

Request

Content-Type: X: "I am sending you X"
Accept: Y: "Please respond with Y"

Response:

Content-Type: X: "I am sending you X"


So when reading the request body, look at Content-Type to decide if the body is PB or JSON. When writing the response body, look at Accept to see whether the client wants PB or JSON, and set Content-Type to the format that the client asked for.


Also, if it's simple, it would be good to include the protobuf name in the content type. For JSON:

Content-Type: application/json;<package name.message name>

and for PB:

Content-Type: application/x.prottp;<package name.message name>

Copy link
Contributor Author

@sunfmin sunfmin Oct 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

snip20171019_16

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept

to fully implement accept specification seems quite complicated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to fully implement accept specification

Ah, sorry, I wasn't really suggesting implementing full support, e.g. q-factor weighting. Just a simple version that can handle either application/json or application/x.prottp.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to fully implement accept specification seems quite complicated.

It's odd that it's not in the standard library. Accept-Language uses the same format...

@sunfmin
Copy link
Contributor Author

sunfmin commented Oct 19, 2017

@bodhi PTAL

},
ExpectedHeadersDump: `HTTP/1.1 200 OK
Content-Length: 31
Content-Type: application/x.prottp;<*example.SearchResponse>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, another unclear description on my part.

With

Content-Type: application/json;<package name.message name>

<> were intended as placeholders, not as part of the content.

Also, I was wrong about the "parameter" (bit after ;), it needs to be <key>=<value> (and key cannot start with q...).

So instead of this:

Content-Type: application/x.prottp;<*example.SearchResponse>

I was asking for it to be this:

Content-Type: application/x.prottp;name=example.SearchResponse

I'm flexible with name. Could be messageName, ms, type, message, etc...

And it looks like you can get the message name via proto.MessageName so that would be better than using the Go type name. Especially since messages are pointers!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

Copy link
Member

@bodhi bodhi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functionally looks fine to me, there are some small changes you can make to make the code simpler.

var err error
var isJSON = isMimeTypeJSON(w.Header().Get("Content-Type"))
if w.Header().Get("Content-Type") == "" {
isJSON = shouldReturnJSON(r)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way you use these conditionals seems a bit weird. I don't really follow why there are several checks about the content type header and isJson.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var isJSON = isMimeTypeJSON(w.Header().Get("Content-Type"))
if w.Header().Get("Content-Type") == "" {

is for other middleware can set the Content-Type, in that case, we use their settings

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

situations:

  1. Middleware set the ContentType by using w.Header().Set() to JSON, prottp should return JSON
  2. HTTP Header Accept is JSON, prottp should return JSON
  3. HTTP Request Content-Type is JSON, prottp should return JSON

prottp.go Outdated
if isJSON {
w.Header().Set("Content-Type", fmt.Sprintf("%s;type=%s", jsonContentType, proto.MessageName(msg)))
} else {
w.Header().Set("Content-Type", fmt.Sprintf("%s;type=%s", xprottpContentType, proto.MessageName(msg)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minimise the code inside the conditionals from "set the content type header to the content type and the name of the message" to the actual difference: "figure out the content type", then below that, do the common work:

-if isJSON {
-	w.Header().Set("Content-Type", fmt.Sprintf("%s;type=%s", jsonContentType, proto.MessageName(msg)))
-} else {
-	w.Header().Set("Content-Type", fmt.Sprintf("%s;type=%s", xprottpContentType, proto.MessageName(msg)))
-}
+contentType := xprottpContentType
+if isJSON {
+	contentType = jsonContentType
+}
+w.Header().Set("Content-Type", fmt.Sprintf("%s;type=%s", contentType, proto.MessageName(msg)))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will fix this.


if isJson {
// start write body
if isJSON {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason why this check of isJSON can't be unified with the check above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can's start writing body, with out first w.WriteHeader write headers.

@sunfmin sunfmin merged commit 30c99d1 into master Oct 22, 2017
@sunfmin sunfmin deleted the export_write_message branch October 22, 2017 04:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants