snoopdave commented on code in PR #161:
URL: https://github.com/apache/roller/pull/161#discussion_r4238359882
##########
app/src/main/java/org/apache/roller/weblogger/webservices/atomprotocol/RollerAtomServlet.java:
##########
@@ -63,102 +55,110 @@
private static final String ATOM_CONTENT_TYPE = "application/atom+xml";
- /**
- * Request attribute that carries the handler authenticated by this servlet
- * to {@link RollerAtomHandlerFactory}, so Propono does not authenticate
the
- * request a second time.
- */
- static final String HANDLER_ATTRIBUTE = RollerAtomServlet.class.getName()
+ ".handler";
-
@Override
- protected void service(HttpServletRequest req, HttpServletResponse res)
- throws ServletException, IOException {
+ protected void service(HttpServletRequest request, HttpServletResponse
response)
+ throws IOException {
if
(!WebloggerRuntimeConfig.getBooleanProperty("webservices.enableAtomPub")) {
- LOG.debug("AtomPub service is disabled; rejecting request");
- sendText(res, HttpServletResponse.SC_NOT_FOUND, "AtomPub service
is disabled");
+ log.debug("AtomPub service is disabled; rejecting request");
+ sendText(response, HttpServletResponse.SC_NOT_FOUND, "AtomPub
service is disabled");
return;
}
- if (!carriesEntry(req)) {
- forward(req, res);
+ String method = request.getMethod();
+ if (!"GET".equals(method) && !"POST".equals(method)
+ && !"PUT".equals(method) && !"DELETE".equals(method)) {
+ response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
- // Authenticate before reading the body, as Propono does.
- AtomHandler handler = createHandler(req, res);
- if (handler.getAuthenticatedUsername() == null) {
- res.setHeader("WWW-Authenticate", "BASIC realm=\"AtomPub\"");
- res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ // Authenticate before reading the body.
+ RollerAtomHandler handler = createHandler(request, response);
+ String userName = handler.getAuthenticatedUsername();
+ if (userName == null) {
+ // The OAuth path may have already written a challenge/error
response.
+ if (!response.isCommitted()) {
+ response.setHeader("WWW-Authenticate", "Basic
realm=\"Roller\"");
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ }
return;
}
- req.setAttribute(HANDLER_ATTRIBUTE, handler);
- int maxEntryBytes = maxEntryBytes();
- // Read one byte past the limit, so an oversized body can be detected.
- byte[] body = req.getInputStream().readNBytes(maxEntryBytes + 1);
- if (body.length > maxEntryBytes) {
- sendText(res, HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE,
"Entry is too large");
+ if ("POST".equals(method) && request.getContentType() == null) {
+ sendText(response, HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE,
+ "No content-type specified in request");
return;
}
- DefaultHandler contentHandler = new DefaultHandler() {
- @Override
- public void error(SAXParseException e) throws SAXException {
- throw e;
+
+ AtomRequest areq;
+ AtomEntry entry = null;
+ if (carriesEntry(request)) {
+ int maxEntryBytes = maxEntryBytes();
+ // Read one byte past the limit, so an oversized body can be
detected.
+ byte[] body = request.getInputStream().readNBytes(maxEntryBytes +
1);
+ if (body.length > maxEntryBytes) {
+ sendText(response,
HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE,
+ "Entry is too large");
+ return;
}
- };
- XMLReader reader;
- try {
- reader =
SecureXmlParsers.newSAXParserFactory().newSAXParser().getXMLReader();
- // Hardening: DOCTYPE declarations should be rejected,
- // regardless whether the secure reader already does it.
- DefaultHandler2 doctypeRefuser = new DefaultHandler2() {
- @Override
- public void startDTD(String name, String publicId, String
systemId)
- throws SAXException {
- throw new SAXException("DOCTYPE is not allowed in an Atom
entry");
- }
- };
-
reader.setProperty("http://xml.org/sax/properties/lexical-handler",
doctypeRefuser);
- } catch (ParserConfigurationException | SAXException e) {
- throw new ServletException("Could not create an Atom entry
parser", e);
+ try {
+ entry = new AtomReader().parseEntry(new
ByteArrayInputStream(body));
+ } catch (AtomException e) {
+ log.debug("Rejecting Atom entry that could not be parsed", e);
+ sendText(response, HttpServletResponse.SC_BAD_REQUEST,
"Invalid Atom entry");
+ return;
+ }
+ areq = new AtomRequest(request, body);
+ } else {
+ // Media bodies are streamed to a temporary file by
MediaCollection,
+ // where the upload size and quota are checked.
+ areq = AtomRequest.streaming(request);
}
- reader.setContentHandler(contentHandler);
- reader.setErrorHandler(contentHandler);
+
try {
- // Propono reads the entry as UTF-8 text, so check the same text.
- reader.parse(new InputSource(new InputStreamReader(
- new ByteArrayInputStream(body), StandardCharsets.UTF_8)));
- } catch (SAXException e) {
- LOG.debug("Rejecting Atom entry that could not be parsed", e);
- sendText(res, HttpServletResponse.SC_BAD_REQUEST, "Invalid Atom
entry");
- return;
+ switch (method) {
+ case "GET":
+ doGet(handler, areq, response);
+ break;
+ case "POST":
+ doPost(handler, areq, entry, response);
+ break;
+ case "PUT":
+ doPut(handler, areq, entry, response);
+ break;
+ default:
+ handler.deleteEntry(areq);
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+ } catch (AtomException ae) {
+ log.debug("Returning error to client: " + ae.getMessage(), ae);
+ if (!response.isCommitted()) {
+ response.sendError(ae.getStatus(), ae.getMessage());
Review Comment:
🤖Claude: fixed by sending only the status code for 5xx AtomExceptions and
logging the details server-side. 4xx responses keep their message, which Roller
writes for the client (for example "Cannot find specified resource").
##########
app/src/main/java/org/apache/roller/weblogger/webservices/atomprotocol/RollerAtomServlet.java:
##########
@@ -63,102 +55,110 @@
private static final String ATOM_CONTENT_TYPE = "application/atom+xml";
- /**
- * Request attribute that carries the handler authenticated by this servlet
- * to {@link RollerAtomHandlerFactory}, so Propono does not authenticate
the
- * request a second time.
- */
- static final String HANDLER_ATTRIBUTE = RollerAtomServlet.class.getName()
+ ".handler";
-
@Override
- protected void service(HttpServletRequest req, HttpServletResponse res)
- throws ServletException, IOException {
+ protected void service(HttpServletRequest request, HttpServletResponse
response)
+ throws IOException {
if
(!WebloggerRuntimeConfig.getBooleanProperty("webservices.enableAtomPub")) {
- LOG.debug("AtomPub service is disabled; rejecting request");
- sendText(res, HttpServletResponse.SC_NOT_FOUND, "AtomPub service
is disabled");
+ log.debug("AtomPub service is disabled; rejecting request");
+ sendText(response, HttpServletResponse.SC_NOT_FOUND, "AtomPub
service is disabled");
return;
}
- if (!carriesEntry(req)) {
- forward(req, res);
+ String method = request.getMethod();
+ if (!"GET".equals(method) && !"POST".equals(method)
+ && !"PUT".equals(method) && !"DELETE".equals(method)) {
+ response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
- // Authenticate before reading the body, as Propono does.
- AtomHandler handler = createHandler(req, res);
- if (handler.getAuthenticatedUsername() == null) {
- res.setHeader("WWW-Authenticate", "BASIC realm=\"AtomPub\"");
- res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ // Authenticate before reading the body.
+ RollerAtomHandler handler = createHandler(request, response);
+ String userName = handler.getAuthenticatedUsername();
+ if (userName == null) {
+ // The OAuth path may have already written a challenge/error
response.
+ if (!response.isCommitted()) {
+ response.setHeader("WWW-Authenticate", "Basic
realm=\"Roller\"");
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ }
return;
}
- req.setAttribute(HANDLER_ATTRIBUTE, handler);
- int maxEntryBytes = maxEntryBytes();
- // Read one byte past the limit, so an oversized body can be detected.
- byte[] body = req.getInputStream().readNBytes(maxEntryBytes + 1);
- if (body.length > maxEntryBytes) {
- sendText(res, HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE,
"Entry is too large");
+ if ("POST".equals(method) && request.getContentType() == null) {
+ sendText(response, HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE,
+ "No content-type specified in request");
return;
}
- DefaultHandler contentHandler = new DefaultHandler() {
- @Override
- public void error(SAXParseException e) throws SAXException {
- throw e;
+
+ AtomRequest areq;
+ AtomEntry entry = null;
+ if (carriesEntry(request)) {
+ int maxEntryBytes = maxEntryBytes();
+ // Read one byte past the limit, so an oversized body can be
detected.
+ byte[] body = request.getInputStream().readNBytes(maxEntryBytes +
1);
+ if (body.length > maxEntryBytes) {
+ sendText(response,
HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE,
+ "Entry is too large");
+ return;
}
- };
- XMLReader reader;
- try {
- reader =
SecureXmlParsers.newSAXParserFactory().newSAXParser().getXMLReader();
- // Hardening: DOCTYPE declarations should be rejected,
- // regardless whether the secure reader already does it.
- DefaultHandler2 doctypeRefuser = new DefaultHandler2() {
- @Override
- public void startDTD(String name, String publicId, String
systemId)
- throws SAXException {
- throw new SAXException("DOCTYPE is not allowed in an Atom
entry");
- }
- };
-
reader.setProperty("http://xml.org/sax/properties/lexical-handler",
doctypeRefuser);
- } catch (ParserConfigurationException | SAXException e) {
- throw new ServletException("Could not create an Atom entry
parser", e);
+ try {
+ entry = new AtomReader().parseEntry(new
ByteArrayInputStream(body));
+ } catch (AtomException e) {
+ log.debug("Rejecting Atom entry that could not be parsed", e);
+ sendText(response, HttpServletResponse.SC_BAD_REQUEST,
"Invalid Atom entry");
+ return;
+ }
+ areq = new AtomRequest(request, body);
+ } else {
+ // Media bodies are streamed to a temporary file by
MediaCollection,
+ // where the upload size and quota are checked.
+ areq = AtomRequest.streaming(request);
}
- reader.setContentHandler(contentHandler);
- reader.setErrorHandler(contentHandler);
+
try {
- // Propono reads the entry as UTF-8 text, so check the same text.
- reader.parse(new InputSource(new InputStreamReader(
- new ByteArrayInputStream(body), StandardCharsets.UTF_8)));
- } catch (SAXException e) {
- LOG.debug("Rejecting Atom entry that could not be parsed", e);
- sendText(res, HttpServletResponse.SC_BAD_REQUEST, "Invalid Atom
entry");
- return;
+ switch (method) {
+ case "GET":
+ doGet(handler, areq, response);
+ break;
+ case "POST":
+ doPost(handler, areq, entry, response);
+ break;
+ case "PUT":
+ doPut(handler, areq, entry, response);
+ break;
+ default:
+ handler.deleteEntry(areq);
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+ } catch (AtomException ae) {
+ log.debug("Returning error to client: " + ae.getMessage(), ae);
+ if (!response.isCommitted()) {
+ response.sendError(ae.getStatus(), ae.getMessage());
+ }
+ } catch (Exception e) {
+ log.error("Unexpected error handling AtomPub request", e);
+ if (!response.isCommitted()) {
+
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
e.getMessage());
Review Comment:
🤖Claude: fixed by no longer sending e.getMessage() for unexpected
exceptions; the client gets a bare 500 and the exception is logged. Test:
serverErrorsDoNotExposeTheExceptionMessage.
##########
app/src/main/java/org/apache/roller/weblogger/webservices/atomprotocol/RollerAtomServlet.java:
##########
@@ -188,61 +188,94 @@
res.getWriter().write(message);
}
- /** A request whose body has already been read into memory. */
- static final class BufferedBodyRequest extends HttpServletRequestWrapper {
+ private void doGet(RollerAtomHandler handler, AtomRequest areq,
HttpServletResponse response)
+ throws AtomException, IOException {
- private final byte[] body;
+ if (handler.isAtomServiceURI(areq)) {
+ AtomServiceDoc service = handler.getAtomService(areq);
+ response.setContentType(AtomConstants.SERVICE_MEDIA_TYPE);
+ new AtomWriter().writeServiceDoc(response.getOutputStream(),
service);
- BufferedBodyRequest(HttpServletRequest request, byte[] body) {
- super(request);
- this.body = body;
- }
+ } else if (handler.isCollectionURI(areq)) {
+ AtomFeed feed = handler.getCollection(areq);
+ response.setContentType(AtomConstants.FEED_MEDIA_TYPE);
+ new AtomWriter().writeFeed(response.getOutputStream(), feed);
- @Override
- public ServletInputStream getInputStream() {
- final ByteArrayInputStream in = new ByteArrayInputStream(body);
- return new ServletInputStream() {
- @Override
- public int read() {
- return in.read();
- }
+ } else if (handler.isEntryURI(areq)) {
+ AtomEntry entry = handler.getEntry(areq);
+ response.setContentType(AtomConstants.ENTRY_MEDIA_TYPE);
+ new AtomWriter().writeEntry(response.getOutputStream(), entry);
- @Override
- public int read(byte[] b, int off, int len) {
- return in.read(b, off, len);
- }
+ } else if (handler.isMediaEditURI(areq)) {
+ AtomMediaResource resource = handler.getMediaResource(areq);
+ if (resource.getContentType() != null) {
+ response.setContentType(resource.getContentType());
+ }
+ response.setContentLengthLong(resource.getContentLength());
+ if (resource.getLastModified() != null) {
+ response.setDateHeader("Last-Modified",
resource.getLastModified().getTime());
+ }
+ try (InputStream in = resource.getInputStream()) {
+ in.transferTo(response.getOutputStream());
+ }
- @Override
- public boolean isFinished() {
- return in.available() == 0;
- }
+ } else {
+ throw new AtomNotFoundException("Cannot find specified resource");
+ }
+ }
- @Override
- public boolean isReady() {
- return true;
- }
+ private void doPost(RollerAtomHandler handler, AtomRequest areq, AtomEntry
entry,
+ HttpServletResponse response) throws AtomException {
- @Override
- public void setReadListener(ReadListener listener) {
- throw new UnsupportedOperationException();
- }
- };
+ if (!handler.isCollectionURI(areq)) {
+ throw new AtomNotFoundException("Cannot POST to specified URI");
}
- @Override
- public BufferedReader getReader() {
- return new BufferedReader(new InputStreamReader(
- new ByteArrayInputStream(body), StandardCharsets.UTF_8));
+ String contentType = areq.getContentType();
+ AtomEntry created;
+ if (entry != null) {
+ created = handler.postEntry(areq, entry);
+ } else {
+ // Media POST: synthesize an entry carrying the request content
type
+ // and Slug; the binary data is read from the request body.
+ AtomEntry mediaEntry = new AtomEntry();
+ AtomContent content = new AtomContent();
+ content.setType(contentType);
+ mediaEntry.setContent(content);
+ mediaEntry.setTitle(areq.getHeader("Slug"));
+ created = handler.postMedia(areq, mediaEntry);
}
+ writeCreated(response, created);
+ }
- @Override
- public int getContentLength() {
- return body.length;
+ private void doPut(RollerAtomHandler handler, AtomRequest areq, AtomEntry
entry,
+ HttpServletResponse response) throws AtomException {
+
+ if (entry != null) {
+ handler.putEntry(areq, entry);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } else if (handler.isMediaEditURI(areq)) {
+ handler.putMedia(areq);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } else {
+ throw new AtomNotFoundException("Cannot PUT to specified URI");
}
+ }
- @Override
- public long getContentLengthLong() {
- return body.length;
+ private void writeCreated(HttpServletResponse response, AtomEntry entry)
+ throws AtomException {
+ String editHref = entry.getLinkHref("edit");
+ if (editHref != null) {
+ response.setHeader("Location", editHref);
Review Comment:
🤖Claude: fixed by adding RollerAtomServlet.safeLocation():
Location/Content-Location are set only when the edit URI starts with this
server's AtomPub URL (from the URL strategy) and parses as a URI; otherwise the
header is omitted. Tests: locationMustBeAValidUriUnderTheAtomUrl,
createdEntryLocationIsSetOnlyWhenSafe.
##########
app/src/main/java/org/apache/roller/weblogger/webservices/atomprotocol/RollerAtomServlet.java:
##########
@@ -188,61 +188,94 @@
res.getWriter().write(message);
}
- /** A request whose body has already been read into memory. */
- static final class BufferedBodyRequest extends HttpServletRequestWrapper {
+ private void doGet(RollerAtomHandler handler, AtomRequest areq,
HttpServletResponse response)
+ throws AtomException, IOException {
- private final byte[] body;
+ if (handler.isAtomServiceURI(areq)) {
+ AtomServiceDoc service = handler.getAtomService(areq);
+ response.setContentType(AtomConstants.SERVICE_MEDIA_TYPE);
+ new AtomWriter().writeServiceDoc(response.getOutputStream(),
service);
- BufferedBodyRequest(HttpServletRequest request, byte[] body) {
- super(request);
- this.body = body;
- }
+ } else if (handler.isCollectionURI(areq)) {
+ AtomFeed feed = handler.getCollection(areq);
+ response.setContentType(AtomConstants.FEED_MEDIA_TYPE);
+ new AtomWriter().writeFeed(response.getOutputStream(), feed);
- @Override
- public ServletInputStream getInputStream() {
- final ByteArrayInputStream in = new ByteArrayInputStream(body);
- return new ServletInputStream() {
- @Override
- public int read() {
- return in.read();
- }
+ } else if (handler.isEntryURI(areq)) {
+ AtomEntry entry = handler.getEntry(areq);
+ response.setContentType(AtomConstants.ENTRY_MEDIA_TYPE);
+ new AtomWriter().writeEntry(response.getOutputStream(), entry);
- @Override
- public int read(byte[] b, int off, int len) {
- return in.read(b, off, len);
- }
+ } else if (handler.isMediaEditURI(areq)) {
+ AtomMediaResource resource = handler.getMediaResource(areq);
+ if (resource.getContentType() != null) {
+ response.setContentType(resource.getContentType());
+ }
+ response.setContentLengthLong(resource.getContentLength());
+ if (resource.getLastModified() != null) {
+ response.setDateHeader("Last-Modified",
resource.getLastModified().getTime());
+ }
+ try (InputStream in = resource.getInputStream()) {
+ in.transferTo(response.getOutputStream());
+ }
- @Override
- public boolean isFinished() {
- return in.available() == 0;
- }
+ } else {
+ throw new AtomNotFoundException("Cannot find specified resource");
+ }
+ }
- @Override
- public boolean isReady() {
- return true;
- }
+ private void doPost(RollerAtomHandler handler, AtomRequest areq, AtomEntry
entry,
+ HttpServletResponse response) throws AtomException {
- @Override
- public void setReadListener(ReadListener listener) {
- throw new UnsupportedOperationException();
- }
- };
+ if (!handler.isCollectionURI(areq)) {
+ throw new AtomNotFoundException("Cannot POST to specified URI");
}
- @Override
- public BufferedReader getReader() {
- return new BufferedReader(new InputStreamReader(
- new ByteArrayInputStream(body), StandardCharsets.UTF_8));
+ String contentType = areq.getContentType();
+ AtomEntry created;
+ if (entry != null) {
+ created = handler.postEntry(areq, entry);
+ } else {
+ // Media POST: synthesize an entry carrying the request content
type
+ // and Slug; the binary data is read from the request body.
+ AtomEntry mediaEntry = new AtomEntry();
+ AtomContent content = new AtomContent();
+ content.setType(contentType);
+ mediaEntry.setContent(content);
+ mediaEntry.setTitle(areq.getHeader("Slug"));
+ created = handler.postMedia(areq, mediaEntry);
}
+ writeCreated(response, created);
+ }
- @Override
- public int getContentLength() {
- return body.length;
+ private void doPut(RollerAtomHandler handler, AtomRequest areq, AtomEntry
entry,
+ HttpServletResponse response) throws AtomException {
+
+ if (entry != null) {
+ handler.putEntry(areq, entry);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } else if (handler.isMediaEditURI(areq)) {
+ handler.putMedia(areq);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } else {
+ throw new AtomNotFoundException("Cannot PUT to specified URI");
}
+ }
- @Override
- public long getContentLengthLong() {
- return body.length;
+ private void writeCreated(HttpServletResponse response, AtomEntry entry)
+ throws AtomException {
+ String editHref = entry.getLinkHref("edit");
+ if (editHref != null) {
+ response.setHeader("Location", editHref);
Review Comment:
🤖Claude: fixed by building the header value with new
URI(href).toASCIIString(), which rejects CR/LF and other illegal characters and
percent-encodes non-ASCII. Unsafe values leave the header unset.
##########
app/src/main/java/org/apache/roller/weblogger/webservices/atomprotocol/RollerAtomServlet.java:
##########
@@ -188,61 +188,94 @@
res.getWriter().write(message);
}
- /** A request whose body has already been read into memory. */
- static final class BufferedBodyRequest extends HttpServletRequestWrapper {
+ private void doGet(RollerAtomHandler handler, AtomRequest areq,
HttpServletResponse response)
+ throws AtomException, IOException {
- private final byte[] body;
+ if (handler.isAtomServiceURI(areq)) {
+ AtomServiceDoc service = handler.getAtomService(areq);
+ response.setContentType(AtomConstants.SERVICE_MEDIA_TYPE);
+ new AtomWriter().writeServiceDoc(response.getOutputStream(),
service);
- BufferedBodyRequest(HttpServletRequest request, byte[] body) {
- super(request);
- this.body = body;
- }
+ } else if (handler.isCollectionURI(areq)) {
+ AtomFeed feed = handler.getCollection(areq);
+ response.setContentType(AtomConstants.FEED_MEDIA_TYPE);
+ new AtomWriter().writeFeed(response.getOutputStream(), feed);
- @Override
- public ServletInputStream getInputStream() {
- final ByteArrayInputStream in = new ByteArrayInputStream(body);
- return new ServletInputStream() {
- @Override
- public int read() {
- return in.read();
- }
+ } else if (handler.isEntryURI(areq)) {
+ AtomEntry entry = handler.getEntry(areq);
+ response.setContentType(AtomConstants.ENTRY_MEDIA_TYPE);
+ new AtomWriter().writeEntry(response.getOutputStream(), entry);
- @Override
- public int read(byte[] b, int off, int len) {
- return in.read(b, off, len);
- }
+ } else if (handler.isMediaEditURI(areq)) {
+ AtomMediaResource resource = handler.getMediaResource(areq);
+ if (resource.getContentType() != null) {
+ response.setContentType(resource.getContentType());
+ }
+ response.setContentLengthLong(resource.getContentLength());
+ if (resource.getLastModified() != null) {
+ response.setDateHeader("Last-Modified",
resource.getLastModified().getTime());
+ }
+ try (InputStream in = resource.getInputStream()) {
+ in.transferTo(response.getOutputStream());
+ }
- @Override
- public boolean isFinished() {
- return in.available() == 0;
- }
+ } else {
+ throw new AtomNotFoundException("Cannot find specified resource");
+ }
+ }
- @Override
- public boolean isReady() {
- return true;
- }
+ private void doPost(RollerAtomHandler handler, AtomRequest areq, AtomEntry
entry,
+ HttpServletResponse response) throws AtomException {
- @Override
- public void setReadListener(ReadListener listener) {
- throw new UnsupportedOperationException();
- }
- };
+ if (!handler.isCollectionURI(areq)) {
+ throw new AtomNotFoundException("Cannot POST to specified URI");
}
- @Override
- public BufferedReader getReader() {
- return new BufferedReader(new InputStreamReader(
- new ByteArrayInputStream(body), StandardCharsets.UTF_8));
+ String contentType = areq.getContentType();
+ AtomEntry created;
+ if (entry != null) {
+ created = handler.postEntry(areq, entry);
+ } else {
+ // Media POST: synthesize an entry carrying the request content
type
+ // and Slug; the binary data is read from the request body.
+ AtomEntry mediaEntry = new AtomEntry();
+ AtomContent content = new AtomContent();
+ content.setType(contentType);
+ mediaEntry.setContent(content);
+ mediaEntry.setTitle(areq.getHeader("Slug"));
+ created = handler.postMedia(areq, mediaEntry);
}
+ writeCreated(response, created);
+ }
- @Override
- public int getContentLength() {
- return body.length;
+ private void doPut(RollerAtomHandler handler, AtomRequest areq, AtomEntry
entry,
+ HttpServletResponse response) throws AtomException {
+
+ if (entry != null) {
+ handler.putEntry(areq, entry);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } else if (handler.isMediaEditURI(areq)) {
+ handler.putMedia(areq);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } else {
+ throw new AtomNotFoundException("Cannot PUT to specified URI");
}
+ }
- @Override
- public long getContentLengthLong() {
- return body.length;
+ private void writeCreated(HttpServletResponse response, AtomEntry entry)
+ throws AtomException {
+ String editHref = entry.getLinkHref("edit");
+ if (editHref != null) {
+ response.setHeader("Location", editHref);
+ response.setHeader("Content-Location", editHref);
Review Comment:
🤖Claude: fixed by the same safeLocation() check as Location on the line
above; Content-Location uses the validated value.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]