Closed Jake-Convictional closed 2 years ago
@Jake-Convictional I appreciate for your contribution. I'm ok to expose MHeaders
, however I would like to to discuss your use case to try to find the best solution.
Could you write your use case in details, please?
No problem!
I'm implementing GitHub-style versioning that uses the Accept header to specify the API version being requested. It would typically look something like: Accept: application/vnd.mycompany.2022-01-01+json
.
To enable that, I want to be able to properly parse an Accept header according to the HTTP spec (your library solves that), and then I want to do the following:
application
and sub-type vnd.mycompany.*
["vnd.mycompany.", "2022-01-01"]
pieces.2022-01-01
piece matches a recognized version. If not, error. Otherwise continue.@Jake-Convictional Hm, you have pretty interesting task. I though about some flexible configurations.
Follow to whatever I see in GitHub documentation, I can assume that we have known list of supported versions and response types. At least we can generate it and get it during the HTTP middleware.
Before execution we will generate multiple supported mime types, like:
application/vnd.mycompany.2022-01-01+json
application/vnd.mycompany.2022-01-01+xml
application/vnd.mycompany.2022-03-01+json
application/vnd.mycompany.2022-03-01+xml
In handler we do something like:
supported := []string{"application/vnd.mycompany.2022-01-01+json", "application/vnd.mycompany.2022-01-01+xml", "application/vnd.mycompany.2022-03-01+json", "application/vnd.mycompany.2022-03-01+xml"}
ah := r.Header.Values("Accept")
found := false
var fh MimeHaeader
for _, v := range ah {
ah := mimeheader.ParseAcceptHeader(v)
h, _, m := ah.Negotiate(supported, v)
if m != nil {
if found {
// Two supported headers found, error.
return
}
found = true
fh = h
}
}
// Parse the Accept header and use it as you wish.
@Jake-Convictional probably I'm missing something, but I would like to understand the improvements I can do to the library based on your use case. Is it possible to ask you, please, to provide an example, how the exposed MHeaders
will help you in your task?
Thanks a lot!
@Jake-Convictional I'm also thinking about adding wildcard search support, like vnd.mycompany.*
. But I'm wondering how useful is it?
Also, I would like to add that GitHub-style versioning
looks pretty interesting to me.
Wow thanks for taking the time to put that together! That almost does what I need except for a few things which I don't think would be possible using the package:
found
variable would quite work as I need since I would also want to error out on something like this: Accept: application/vnd.mycompany.2022-01-01+json, application/vnd.mycompany.2022-03-01+json
vnd.mycompany.badversion
whereas omitting the vnd.mycompany
type entirely is okay.supported
list didn't need to matrix with each json
, xml
, etc part of the sub-type.So my preferred way to do this would be:
supported := []string{"2022-01-01", "2022-03-01"}
ah := r.Header.Values("Accept")
found := false
version := ""
var fh MimeHeader
for _, v := range ah {
ah := mimeheader.ParseAcceptHeader(v)
for _, mediaType := range ah.MHeaders {
if mediaType.Type == "application" && strings.HasPrefix(mediaType.SubType, "vnd.mycompany.") {
if found {
// Two supported headers found, error.
return
}
found = true
version = MyRegexToGetTheVersion(mediaType.SubType)
}
}
}
if found {
if !Contains(supported, version) {
// Bad version, error.
return
}
// Do something with the version now
}
In the end, I think AcceptHeader.MHeaders
is a great property to export because every piece of information contained is meaningful/valuable to the caller. MimeHeader
is an exported struct already so it wouldn't expose any unnecessary internals.
@Jake-Convictional Thanks a lot for your example. If you would like to go this route, then exposed MHandler
has a lot of sense.
I'm merging the PR.
Anyway, if you have an idea how to make library more flexible for your task, I'd happy to discuss.
My thoughts are going around comparable interface that can help to extend flexibility.
Thanks a lot for your contribution!
Closes #10
This change makes
AcceptHeaders.MHeaders
an exported property so that users of the package can take advantage of the HTTP-compliant parsing and make use of the results in a flexible manner.For example, I want to match a media type in the Accept header using a custom regex on the
SubType
rather than an exact match.New tests not applicable in this case.