RedirectResource.kt

  1. package com.testainers

  2. import jakarta.ws.rs.*
  3. import jakarta.ws.rs.core.*
  4. import org.eclipse.microprofile.openapi.annotations.media.Schema
  5. import org.eclipse.microprofile.openapi.annotations.parameters.Parameter
  6. import org.eclipse.microprofile.openapi.annotations.responses.APIResponse
  7. import org.eclipse.microprofile.openapi.annotations.responses.APIResponses
  8. import java.net.URI

  9. /**
  10.  * @author Eduardo Folly
  11.  */
  12. @Path("/redirect")
  13. @APIResponses(
  14.     APIResponse(responseCode = "30X", description = "Redirected"),
  15.     APIResponse(
  16.         responseCode = "500",
  17.         description =
  18.             "'Invalid URL' or 'Invalid URL Scheme' " +
  19.                 "or 'Invalid status code: 30X'",
  20.     ),
  21. )
  22. class RedirectResource {
  23.     @GET
  24.     fun get(
  25.         @Parameter(
  26.             description = "URL to redirect.",
  27.             required = true,
  28.         ) @QueryParam("url") @DefaultValue("") url: String,
  29.         @Parameter(
  30.             description = "Response status code.",
  31.             schema = Schema(minimum = "300", maximum = "399"),
  32.         ) @QueryParam("code") @DefaultValue("302") code: Int,
  33.     ): Response = internal(url, code)

  34.     @POST
  35.     fun post(
  36.         @Parameter(
  37.             description = "URL to redirect.",
  38.             required = true,
  39.         ) @QueryParam("url") @DefaultValue("") url: String,
  40.         @Parameter(
  41.             description = "Response status code.",
  42.             schema = Schema(minimum = "300", maximum = "399"),
  43.         ) @QueryParam("code") @DefaultValue("302") code: Int,
  44.     ): Response = internal(url, code)

  45.     @PUT
  46.     fun put(
  47.         @Parameter(
  48.             description = "URL to redirect.",
  49.             required = true,
  50.         ) @QueryParam("url") @DefaultValue("") url: String,
  51.         @Parameter(
  52.             description = "Response status code.",
  53.             schema = Schema(minimum = "300", maximum = "399"),
  54.         ) @QueryParam("code") @DefaultValue("302") code: Int,
  55.     ): Response = internal(url, code)

  56.     @PATCH
  57.     fun patch(
  58.         @Parameter(
  59.             description = "URL to redirect.",
  60.             required = true,
  61.         ) @QueryParam("url") @DefaultValue("") url: String,
  62.         @Parameter(
  63.             description = "Response status code.",
  64.             schema = Schema(minimum = "300", maximum = "399"),
  65.         ) @QueryParam("code") @DefaultValue("302") code: Int,
  66.     ): Response = internal(url, code)

  67.     @DELETE
  68.     fun delete(
  69.         @Parameter(
  70.             description = "URL to redirect.",
  71.             required = true,
  72.         ) @QueryParam("url") @DefaultValue("") url: String,
  73.         @Parameter(
  74.             description = "Response status code.",
  75.             schema = Schema(minimum = "300", maximum = "399"),
  76.         ) @QueryParam("code") @DefaultValue("302") code: Int,
  77.     ): Response = internal(url, code)

  78.     @HEAD
  79.     fun head(
  80.         @Parameter(
  81.             description = "URL to redirect.",
  82.             required = true,
  83.         ) @QueryParam("url") @DefaultValue("") url: String,
  84.         @Parameter(
  85.             description = "Response status code.",
  86.             schema = Schema(minimum = "300", maximum = "399"),
  87.         ) @QueryParam("code") @DefaultValue("302") code: Int,
  88.     ): Response = internal(url, code)

  89.     private fun internal(
  90.         url: String,
  91.         code: Int,
  92.     ): Response {
  93.         val uri: URI

  94.         if (url.isBlank()) {
  95.             return Response
  96.                 .status(500)
  97.                 .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN)
  98.                 .entity("URL is required")
  99.                 .build()
  100.         }

  101.         try {
  102.             uri = URI.create(url)
  103.         } catch (e: Exception) {
  104.             return Response
  105.                 .status(500)
  106.                 .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN)
  107.                 .entity("Invalid URL: $url")
  108.                 .build()
  109.         }

  110.         if (uri.scheme?.startsWith("http") != true) {
  111.             return Response
  112.                 .status(500)
  113.                 .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN)
  114.                 .entity("Invalid URL Scheme: $url")
  115.                 .build()
  116.         }

  117.         if (code < 300 || code > 399) {
  118.             return Response
  119.                 .status(500)
  120.                 .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN)
  121.                 .entity("Invalid status code: $code")
  122.                 .build()
  123.         }

  124.         return Response
  125.             .status(code)
  126.             .header(HttpHeaders.LOCATION, uri.toASCIIString())
  127.             .build()
  128.     }
  129. }