This is an automated email from the ASF dual-hosted git repository.

thiagohp pushed a commit to branch rest
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git


The following commit(s) were added to refs/heads/rest by this push:
     new 569afe2  TAP5-2696: better HttpStatus and OpenAPI viewer styling
569afe2 is described below

commit 569afe24f66fe19ea3b13352d43937f96e135420
Author: Thiago H. de Paula Figueiredo <[email protected]>
AuthorDate: Fri Nov 19 16:09:09 2021 -0300

    TAP5-2696: better HttpStatus and OpenAPI viewer styling
---
 .../HttpStatusComponentEventResultProcessor.java   |   4 +-
 .../org/apache/tapestry5/services/HttpStatus.java  | 169 +++++++++++++++++----
 .../apache/tapestry5/services/HttpStatusTest.java  | 128 ++++++++++++++++
 .../tapestryopenapiviewer/pages/Index.tml          |   8 +-
 4 files changed, 271 insertions(+), 38 deletions(-)

diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/HttpStatusComponentEventResultProcessor.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/HttpStatusComponentEventResultProcessor.java
index 676c9f8..fabe617 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/HttpStatusComponentEventResultProcessor.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/HttpStatusComponentEventResultProcessor.java
@@ -45,10 +45,10 @@ public class HttpStatusComponentEventResultProcessor 
implements ComponentEventRe
             final String headerValue = extraHttpHeaders.get(header);
             response.setHeader(header, headerValue);
         }
-        if (value.getMessage() != null)
+        if (value.getResponseBody() != null)
         {
             Objects.requireNonNull(value.getContentType(), 
"HttpStatus.mimeType cannot be null");
-            
response.getPrintWriter(value.getContentType()).append(value.getMessage()).close();
+            
response.getPrintWriter(value.getContentType()).append(value.getResponseBody()).close();
         }
     }
 }
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/HttpStatus.java 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/HttpStatus.java
index bdc57b0..907f1c3 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/HttpStatus.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/HttpStatus.java
@@ -19,90 +19,163 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
 
+import javax.servlet.http.HttpServletResponse;
+
 import org.apache.tapestry5.StreamResponse;
+import org.apache.tapestry5.http.Link;
 
 /**
+ * <p>
  * An event handler method may return an instance of this class to send an 
specific HTTP status
  * code to the client. It also supports providing a string to be used as the 
response body
- * and extra HTTP headers to be set.
+ * and extra HTTP headers to be set. This class also provides some utility
+ * static methods for creating instances for specific HTTP statuses and a 
fluent API for setting
+ * additional information on them.
+ * </p>
  * 
+ * <p>
  * For returning binary content and/or adding a response header more than once 
and/or
- * adding a response header without overwriting existing ones, implement a 
{@link StreamResponse} 
- * instead.
+ * adding a response header without overwriting existing ones, implementing a 
{@link StreamResponse} 
+ * is the most probable better choice.
+ * </p>
  *
  * @since 5.8.0
  */
 public final class HttpStatus
 {
     private static final String CONTENT_LOCATION_HTTP_HEADER = 
"Content-Location";
+    
+    private static final String LOCATION_HTTP_HEADER = "Location";
 
     private final int statusCode;
 
-    String message;
+    private String responseBody;
     
-    String contentType;
+    private String contentType;
     
-    Map<String, String> extraHttpHeaders;
+    private Map<String, String> extraHttpHeaders;
     
     /**
-     * Creates an object with a given status code and no message.
+     * Creates an instance with status code <code>200 OK</code>.
      */
-    public HttpStatus(int statusCode)
+    public static HttpStatus ok()
     {
-        this(statusCode, null, null);
+        return new HttpStatus(HttpServletResponse.SC_OK);
     }
-    
+
     /**
-     * Creates an object with a given status code, message and 
<code>text/plain</code> MIME content type.
+     * Creates an instance with status code <code>201 Created</code>.
      */
-    public HttpStatus(int statusCode, String message)
+    public static HttpStatus created()
     {
-        this(statusCode, message, "text/plain");
+        return new HttpStatus(HttpServletResponse.SC_CREATED);
     }
 
     /**
-     * Creates an object with a given status code, message and MIME content 
type.
+     * Creates an instance with status code <code>202 Accepted</code>.
      */
-    public HttpStatus(int statusCode, String message, String contentType)
+    public static HttpStatus accepted()
     {
-        this.statusCode = statusCode;
-        this.message = message;
-        this.contentType = contentType;
+        return new HttpStatus(HttpServletResponse.SC_ACCEPTED);
     }
-
+    
     /**
-     * Returns the status code.
+     * Creates an instance with status code <code>303 See Other</code>.
+     * @param location the value of the <code>Location</code> header.
      */
-    public int getStatusCode()
+    public static HttpStatus seeOther(String location)
     {
-        return statusCode;
+        return new 
HttpStatus(HttpServletResponse.SC_SEE_OTHER).withLocation(location);
+    }
+    
+    /**
+     * Creates an instance with status code <code>303 See Also</code>.
+     * @param location the value of the <code>Location</code> header.
+     */
+    public static HttpStatus seeOther(Link location)
+    {
+        return new 
HttpStatus(HttpServletResponse.SC_SEE_OTHER).withLocation(location);
+    }
+    
+    /**
+     * Creates an instance with status code <code>301 Moved Permanently</code>.
+     * @param location the value of the <code>Location</code> header.
+     */
+    public static HttpStatus movedPermanently(String location)
+    {
+        return new 
HttpStatus(HttpServletResponse.SC_MOVED_PERMANENTLY).withLocation(location);
+    }
+    
+    /**
+     * Creates an instance with status code <code>301 Moved Permanently</code>.
+     * @param location the value of the <code>Location</code> header.
+     */
+    public static HttpStatus movedPermanently(Link link)
+    {
+        return movedPermanently(link.toRedirectURI());
+    }
+    
+    /**
+     * Creates an instance with status code <code>302 Found</code>.
+     * @param location the value of the <code>Location</code> header.
+     */
+    public static HttpStatus temporaryRedirect(String location)
+    {
+        return new 
HttpStatus(HttpServletResponse.SC_FOUND).withLocation(location);
+    }
+    
+    /**
+     * Creates an instance with status code <code>302 Found</code>.
+     * @param location the value of the <code>Location</code> header.
+     */
+    public static HttpStatus temporaryRedirect(Link location)
+    {
+        return temporaryRedirect(location.toRedirectURI());
     }
 
     /**
-     * Returns the message.
+     * Creates an object with a given status code and no response body.
      */
-    public String getMessage()
+    public HttpStatus(int statusCode)
     {
-        return message;
+        this(statusCode, null, null);
     }
     
     /**
-     * Returns the extra HTTP headers.
+     * Creates an object with a given status code, response body and 
<code>text/plain</code> MIME content type.
      */
-    @SuppressWarnings("unchecked")
-    public Map<String, String> getExtraHttpHeaders() {
-        return extraHttpHeaders != null ? extraHttpHeaders : 
Collections.EMPTY_MAP;
+    public HttpStatus(int statusCode, String responseBody)
+    {
+        this(statusCode, responseBody, "text/plain");
+    }
+
+    /**
+     * Creates an object with a given status code, response body and MIME 
content type.
+     */
+    public HttpStatus(int statusCode, String responseBody, String contentType)
+    {
+        this.statusCode = statusCode;
+        this.responseBody = responseBody;
+        this.contentType = contentType;
     }
     
     /**
-     * Returns the MIME content type of the message.
+     * Sets a redirect by using the <code>Location</code> HTTP header.
      */
-    public String getContentType() 
+    public HttpStatus withLocation(Link location)
     {
-        return contentType;
+        return withLocation(location.toRedirectURI());
     }
     
     /**
+     * Sets a redirect by using the <code>Location</code> HTTP header.
+     */
+    public HttpStatus withLocation(String location)
+    {
+        return withHttpHeader(LOCATION_HTTP_HEADER, location);
+    }
+
+    /**
      * Sets the <code>Content-Location</code> HTTP header.
      */
     public HttpStatus withContentLocation(String location)
@@ -127,4 +200,36 @@ public final class HttpStatus
         return this;
     }
 
+    /**
+     * Returns the status code.
+     */
+    public int getStatusCode()
+    {
+        return statusCode;
+    }
+
+    /**
+     * Returns the response body.
+     */
+    public String getResponseBody()
+    {
+        return responseBody;
+    }
+
+    /**
+     * Returns the MIME content type of the response body.
+     */
+    public String getContentType() 
+    {
+        return contentType;
+    }
+
+    /**
+     * Returns the extra HTTP headers.
+     */
+    @SuppressWarnings("unchecked")
+    public Map<String, String> getExtraHttpHeaders() {
+        return extraHttpHeaders != null ? extraHttpHeaders : 
Collections.EMPTY_MAP;
+    }
+
 }
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/services/HttpStatusTest.java 
b/tapestry-core/src/test/java/org/apache/tapestry5/services/HttpStatusTest.java
new file mode 100644
index 0000000..a09ea82
--- /dev/null
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/services/HttpStatusTest.java
@@ -0,0 +1,128 @@
+// Copyright 2021 The Apache Software Foundation
+//
+// Licensed 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.apache.tapestry5.services;
+
+import org.apache.tapestry5.http.Link;
+import org.easymock.EasyMock;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+
+import javax.servlet.http.HttpServletResponse;
+
+public class HttpStatusTest
+{
+    
+    private static final String TEST_URL = "http://example.com/something";;
+    
+    private Link link;
+    
+    @BeforeMethod
+    public void setupLink()
+    {
+        link = EasyMock.createMock(Link.class);
+        EasyMock.expect(link.toRedirectURI()).andReturn(TEST_URL).times(0, 1);
+        EasyMock.replay(link);
+    }
+    
+    @AfterMethod
+    public void afterTest()
+    {
+        EasyMock.verify(link);
+    }
+    
+    @Test
+    public void ok()
+    {
+        HttpStatus status = HttpStatus.ok();
+        assertEquals(status.getStatusCode(), HttpServletResponse.SC_OK);
+    }
+
+    @Test
+    public void created()
+    {
+        HttpStatus status = HttpStatus.created();
+        assertEquals(status.getStatusCode(), HttpServletResponse.SC_CREATED);
+    }
+    
+    @Test
+    public void accepted()
+    {
+        HttpStatus status = HttpStatus.accepted();
+        assertEquals(status.getStatusCode(), HttpServletResponse.SC_ACCEPTED);
+    }
+    
+    @Test
+    public void seeOtherWithString()
+    {
+        HttpStatus status = HttpStatus.seeOther(TEST_URL);
+        assertEquals(status.getStatusCode(), HttpServletResponse.SC_SEE_OTHER);
+        assertEquals(getLocation(status), TEST_URL);
+    }
+
+    @Test
+    public void seeOtherWithLink()
+    {
+        HttpStatus status = HttpStatus.seeOther(link);
+        assertEquals(status.getStatusCode(), HttpServletResponse.SC_SEE_OTHER);
+    }
+    
+    @Test
+    public void movedPermanentlyWithString()
+    {
+        HttpStatus status = HttpStatus.movedPermanently(TEST_URL);
+        assertEquals(status.getStatusCode(), 
HttpServletResponse.SC_MOVED_PERMANENTLY);
+        assertEquals(getLocation(status), TEST_URL);
+    }
+
+    @Test
+    public void movedPermanentlyWithLink()
+    {
+        HttpStatus status = HttpStatus.movedPermanently(link);
+        assertEquals(status.getStatusCode(), 
HttpServletResponse.SC_MOVED_PERMANENTLY);
+    }
+    
+    @Test
+    public void temporaryRedirectWithString()
+    {
+        HttpStatus status = HttpStatus.temporaryRedirect(TEST_URL);
+        assertEquals(status.getStatusCode(), HttpServletResponse.SC_FOUND);
+        assertEquals(getLocation(status), TEST_URL);
+    }
+
+    @Test
+    public void temporaryRedirectWithLink()
+    {
+        HttpStatus status = HttpStatus.temporaryRedirect(link);
+        assertEquals(status.getStatusCode(), HttpServletResponse.SC_FOUND);
+    }
+    
+    @Test
+    public void withContentLocation()
+    {
+        HttpStatus status = HttpStatus.created().withContentLocation(TEST_URL);
+        assertEquals(getContentLocation(status), TEST_URL);
+    }
+
+    private String getLocation(HttpStatus status) {
+        return status.getExtraHttpHeaders().get("Location");
+    }
+    
+    private String getContentLocation(HttpStatus status) {
+        return status.getExtraHttpHeaders().get("Content-Location");
+    }
+
+}
diff --git 
a/tapestry-openapi-viewer/src/main/resources/org/apache/tapestry5/tapestryopenapiviewer/pages/Index.tml
 
b/tapestry-openapi-viewer/src/main/resources/org/apache/tapestry5/tapestryopenapiviewer/pages/Index.tml
index 06994c4..750b08d 100644
--- 
a/tapestry-openapi-viewer/src/main/resources/org/apache/tapestry5/tapestryopenapiviewer/pages/Index.tml
+++ 
b/tapestry-openapi-viewer/src/main/resources/org/apache/tapestry5/tapestryopenapiviewer/pages/Index.tml
@@ -32,7 +32,7 @@
       }
       pre.version
       {
-        color: black !important;
+        background-color: inherit;
       }
       .swagger-ui-attribution
       {
@@ -82,11 +82,11 @@
 <!--                                                   alt="Online validator 
badge"/> -->
 <!--                                   </a> -->
 <!--                           </span> -->
+              <p class="swagger-ui-attribution">
+                This OpenAPI definition viewer is based on <a 
href="https://swagger.io/tools/swagger-ui/";>Swagger UI</a>.
+              </p>
                        </section>
                </div>
        </div>
-  <p class="swagger-ui-attribution">
-    This OpenAPI definition viewer is based on <a 
href="https://swagger.io/tools/swagger-ui/";>Swagger UI</a>.
-  </p>
   </body>
 </html>
\ No newline at end of file

Reply via email to