-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
Media-type parser #61987
Media-type parser #61987
Changes from 1 commit
5e42390
01f001d
50a88a0
fb03ffd
09f281e
8bc024f
070508c
3c7ab16
59a7f42
968b1c9
46f8f33
cbbe093
222caee
6bdec13
ee97564
7f52e11
63db70c
57ddb40
b5f1eff
90e798d
fa49be4
31d92ac
a925fbe
23c4e41
b1e3fb1
c17a895
7d6bd08
3c93954
77068a8
8fb0cd4
63fb6c7
4598a0a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* Licensed to Elasticsearch under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
package org.elasticsearch.common.xcontent; | ||
|
||
import java.util.Map; | ||
|
||
public interface MediaType { | ||
String type(); | ||
String subtype(); | ||
String format(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Format, shortName, and subType seem like 3 ways to represent the same thing, and would be great if we could get to a common term ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in some cases these 3 are actually different. For instance - I think shortName is redundant and I will give it a go to remove it |
||
|
||
default String typeSubtype(){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return type()+"/"+subtype(); | ||
pgomulka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* Licensed to Elasticsearch under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
package org.elasticsearch.common.xcontent; | ||
|
||
import java.util.HashMap; | ||
import java.util.Locale; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
public class XContentTypeParser<T extends MediaType> { | ||
private Map<String, T> formatToXContentType = new HashMap<>(); | ||
private Map<String, T> typeSubtypeToMediaType = new HashMap<>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: |
||
|
||
public XContentTypeParser(T[] acceptedXContentTypes) { | ||
for (T xContentType : acceptedXContentTypes) { | ||
typeSubtypeToMediaType.put(xContentType.typeSubtype(), xContentType); | ||
formatToXContentType.put(xContentType.format(), xContentType); | ||
} | ||
} | ||
|
||
public T fromMediaType(String contentTypeHeader) { | ||
ParsedMediaType parsedMediaType = parseMediaType(contentTypeHeader); | ||
return parsedMediaType != null ? parsedMediaType.getMediaType() : null; | ||
} | ||
|
||
public T fromFormat(String mediaType) { | ||
return formatToXContentType.get(mediaType.toLowerCase(Locale.ROOT)); | ||
} | ||
|
||
public XContentTypeParser withAdditionalMediaType(String typeSubtype, T xContentType) { | ||
typeSubtypeToMediaType.put(typeSubtype.toLowerCase(Locale.ROOT), xContentType); | ||
formatToXContentType.put(xContentType.format(), xContentType); | ||
return this; | ||
} | ||
|
||
public ParsedMediaType parseMediaType(String mediaType) { | ||
if (mediaType != null) { | ||
String headerValue = mediaType.toLowerCase(Locale.ROOT); | ||
// split string on semicolon | ||
// validate media type is accepted (IIRC whitespace is ok so trim it) //TODO PG whitespace only ok in params | ||
// rest of strings are params. validate per RFC 7230 and use ones that we care about | ||
// or use a regex and we can change if necessary | ||
String[] split = headerValue.split(";"); | ||
|
||
String[] typeSubtype = split[0].toLowerCase(Locale.ROOT) | ||
.split("/"); | ||
if (typeSubtype.length == 2) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I completely follow the The previous version accepted either variants (format ( I see two cases Is possible to just support the mime type for all content-type and accept header parsing ? (leaving the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 4x yes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks.. i double checked I have not validated There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
String type = typeSubtype[0]; | ||
String subtype = typeSubtype[1]; | ||
T xContentType = typeSubtypeToMediaType.get(type + "/" + subtype); | ||
if (xContentType != null) { | ||
Map<String, String> parameters = new HashMap<>(); | ||
for (int i = 1; i < split.length; i++) { | ||
String[] keyValueParam = split[i].trim().split("="); | ||
parameters.put(keyValueParam[0].toLowerCase(Locale.ROOT), keyValueParam[1].toLowerCase(Locale.ROOT)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you need to check for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good point, will add test cases |
||
} | ||
return new ParsedMediaType(type, subtype, parameters, xContentType); | ||
} | ||
} | ||
|
||
} | ||
return null; | ||
} | ||
|
||
public class ParsedMediaType { | ||
private final String type; | ||
private final String subtype; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good point, will remove |
||
private final Map<String, String> parameters; | ||
private final T xContentType; | ||
|
||
public ParsedMediaType(String type, String subtype, Map<String, String> parameters, T xContentType) { | ||
this.type = type; | ||
this.subtype = subtype; | ||
this.parameters = parameters; | ||
this.xContentType = xContentType; | ||
} | ||
|
||
public T getMediaType() { | ||
return xContentType; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
ParsedMediaType parsedMediaType = (ParsedMediaType) o; | ||
return Objects.equals(type, parsedMediaType.type) && | ||
Objects.equals(subtype, parsedMediaType.subtype) && | ||
Objects.equals(parameters, parsedMediaType.parameters) && | ||
xContentType == parsedMediaType.xContentType; | ||
} | ||
|
||
public Map<String, String> getParameters() { | ||
return parameters; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* Licensed to Elasticsearch under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
package org.elasticsearch.common.xcontent; | ||
|
||
import org.elasticsearch.test.ESTestCase; | ||
|
||
import java.util.Collections; | ||
import java.util.Map; | ||
|
||
import static org.hamcrest.Matchers.equalTo; | ||
|
||
public class XContentTypeParserTests extends ESTestCase { | ||
XContentTypeParser xContentTypeParser = XContentType.xContentTypeParser; | ||
|
||
public void testJsonWithParameters() throws Exception { | ||
String mediaType = "application/json"; | ||
assertThat(xContentTypeParser.parseMediaType(mediaType).getParameters(), | ||
equalTo(Collections.emptyMap())); | ||
assertThat(xContentTypeParser.parseMediaType(mediaType + ";").getParameters(), | ||
equalTo(Collections.emptyMap())); | ||
assertThat(xContentTypeParser.parseMediaType(mediaType + "; charset=UTF-8").getParameters(), | ||
equalTo(Map.of("charset", "utf-8"))); | ||
assertThat(xContentTypeParser.parseMediaType(mediaType + "; custom=123;charset=UTF-8").getParameters(), | ||
equalTo(Map.of("charset", "utf-8", "custom", "123"))); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add javadocs to the class and methods?