HDDS-13258. Refactor HttpServletResponse (Part1 - HddsConfServlet)#9126
Conversation
…ml if accept header has invalid value
… specified format
|
@peterxcli Would you like to review this PR ? |
adoroszlai
left a comment
There was a problem hiding this comment.
Thanks @unknowntpo for the patch.
I would prefer ResponseFormat and related static methods to be added/moved outside of HddsConfServlet (and matching new test class).
| private void processCommand(String cmd, ResponseFormat format, | ||
| HttpServletRequest request, HttpServletResponse response, Writer out, | ||
| String name) |
There was a problem hiding this comment.
nit: Please do not format method signature like this. Whenever visibility / return type / method name / other modifiers are changed, we would have to reindent all parameters.
| Writer out) throws IOException { | ||
| Writer out) throws IOException { |
There was a problem hiding this comment.
Please do not format method signature like this.
| switch (format) { | ||
| case JSON: | ||
| response.setContentType("application/json; charset=utf-8"); | ||
| break; | ||
| case XML: | ||
| default: | ||
| response.setContentType("text/xml; charset=utf-8"); | ||
| break; | ||
| } |
There was a problem hiding this comment.
I suggest adding getContentType() instance method in ResponseFormat, returning application/json and text/xml for JSON and XML respectively. Then we can change this to:
| switch (format) { | |
| case JSON: | |
| response.setContentType("application/json; charset=utf-8"); | |
| break; | |
| case XML: | |
| default: | |
| response.setContentType("text/xml; charset=utf-8"); | |
| break; | |
| } | |
| response.setContentType(format.getContentType() + "; charset=utf-8"); |
@adoroszlai Do you want to provide a consistent way to deal with HTTP response for all child class of |
Sounds good. |
|
@adoroszlai Refactoring is done, would you like to review it again ? |
adoroszlai
left a comment
There was a problem hiding this comment.
Thanks @unknowntpo for updating the patch, LGTM.
|
|
||
| private static void writeXmlError(String errorMessage, Writer out) throws IOException { | ||
| try { | ||
| DocumentBuilderFactory factory = XMLUtils.newSecureDocumentBuilderFactory(); |
There was a problem hiding this comment.
I think DocumentBuilderFactory should be stored for reuse.
Once an application has obtained a reference to a
DocumentBuilderFactoryit can use the factory to configure and obtain parser instances. doc
Something like:
private static final CheckedSupplier<DocumentBuilderFactory, ParserConfigurationException> DOCUMENT_BUILDER_FACTORY =
MemoizedCheckedSupplier.valueOf(XMLUtils::newSecureDocumentBuilderFactory);and
DocumentBuilder builder = DOCUMENT_BUILDER_FACTORY.get().newDocumentBuilder();…f/HddsConfServlet.java fix indent Co-authored-by: Doroszlai, Attila <6454655+adoroszlai@users.noreply.github.com>
…f/HddsConfServlet.java fix indent Co-authored-by: Doroszlai, Attila <6454655+adoroszlai@users.noreply.github.com>
…ls/HttpServletUtils.java fix indent Co-authored-by: Doroszlai, Attila <6454655+adoroszlai@users.noreply.github.com>
…ls/TestHttpServletUtils.java fix indent Co-authored-by: Doroszlai, Attila <6454655+adoroszlai@users.noreply.github.com>
|
@adoroszlai Sorry, that indentation problem happens again. |
|
|
@peterxcli please take a look |
| case XML: | ||
| default: | ||
| writeXmlError(errorMessage, writer); | ||
| break; | ||
| } |
There was a problem hiding this comment.
ditto (#9126 (comment))
| case XML: | |
| default: | |
| writeXmlError(errorMessage, writer); | |
| break; | |
| } | |
| case XML: | |
| writeXmlError(errorMessage, writer); | |
| break; | |
| default: | |
| throw ....; | |
| } |
There was a problem hiding this comment.
I throw an IOException, whose cause is IllegalArgumentException to denote that it happened during writing response to I/O, and caller passed in illegal arguments.
…tion for unspecified format
…ch cause is IllegalArgumentException
chungen0126
left a comment
There was a problem hiding this comment.
Thanks @unknowntpo for the patch. Left some comments.
| */ | ||
| public static ResponseFormat getResponseFormat(HttpServletRequest request) throws IllegalArgumentException { | ||
| String format = request.getHeader(HttpHeaders.ACCEPT); | ||
| if (format == null) { |
There was a problem hiding this comment.
My suggestion is to use XML as the fallback when the format is null. For any format other than XML or JSON, we should set it to UNSPECIFIED.
| public enum ResponseFormat { | ||
| UNSPECIFIED("unspecified"), | ||
| JSON("json"), | ||
| XML("xml"); |
There was a problem hiding this comment.
I suggest we use the MediaType constants (e.g., MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML) instead of string literals like "json". This is more precise as it directly uses the values that will be set in the HTTP headers, and it also avoids 'magic strings'.
peterxcli
left a comment
There was a problem hiding this comment.
LGTM! Thanks very much for this improvement!
|
lets merge this after green CI! |
|
Thanks @unknowntpo for this patch, @adoroszlai and @chungen0126 for reviewing! |
| /** | ||
| * Functional interface for operations that accept a parameter and may throw exceptions. | ||
| * | ||
| * @param <T> the type of the input to the operation | ||
| */ | ||
| @FunctionalInterface | ||
| public interface CheckedConsumer<T> { | ||
| void accept(T t) throws Exception; | ||
| } |
There was a problem hiding this comment.
In part 2, I think we should reuse CheckedConsumer from org.apache.ratis.util.function instead of defining new interface.
|
@chungen0126 Sorry I didnt notice that you left some comments
@unknowntpo please address them in the part 2 if you think they make sense to you, thanks! |
This PR:
JSON, orXML, if no format is specified, fall back toXML.ResponseFormatfor readability.What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-13258
How was this patch tested?
UT: TestHddsConfServlet