diff --git a/docs/generators/haskell.md b/docs/generators/haskell.md index 96cfde1fa94..b828257f3f8 100644 --- a/docs/generators/haskell.md +++ b/docs/generators/haskell.md @@ -11,3 +11,4 @@ sidebar_label: haskell |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |modelPackage|package for generated models| |null| |apiPackage|package for generated api classes| |null| +|serveStatic|serve will serve files from the directory 'static'.| |true| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellServantCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellServantCodegen.java index ec30ae275e1..8a0d0980096 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellServantCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellServantCodegen.java @@ -43,6 +43,10 @@ public class HaskellServantCodegen extends DefaultCodegen implements CodegenConf protected String apiVersion = "0.0.1"; private static final Pattern LEADING_UNDERSCORE = Pattern.compile("^_+"); + public static final String PROP_SERVE_STATIC = "serveStatic"; + public static final String PROP_SERVE_STATIC_DESC = "serve will serve files from the directory 'static'."; + public static final Boolean PROP_SERVE_STATIC_DEFAULT = Boolean.TRUE; + /** * Configures the type of generator. * @@ -183,6 +187,15 @@ public class HaskellServantCodegen extends DefaultCodegen implements CodegenConf cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC)); cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC)); + cliOptions.add(new CliOption(PROP_SERVE_STATIC, PROP_SERVE_STATIC_DESC).defaultValue(PROP_SERVE_STATIC_DEFAULT.toString())); + } + + public void setBooleanProperty(String property, Boolean defaultValue) { + if (additionalProperties.containsKey(property)) { + additionalProperties.put(property, convertPropertyToBoolean(property)); + } else { + additionalProperties.put(property, defaultValue); + } } @Override @@ -192,6 +205,8 @@ public class HaskellServantCodegen extends DefaultCodegen implements CodegenConf if (StringUtils.isEmpty(System.getenv("HASKELL_POST_PROCESS_FILE"))) { LOGGER.info("Hint: Environment variable HASKELL_POST_PROCESS_FILE not defined so the Haskell code may not be properly formatted. To define it, try 'export HASKELL_POST_PROCESS_FILE=\"$HOME/.local/bin/hfmt -w\"' (Linux/Mac)"); } + + setBooleanProperty(PROP_SERVE_STATIC, PROP_SERVE_STATIC_DEFAULT); } /** diff --git a/modules/openapi-generator/src/main/resources/haskell-servant/API.mustache b/modules/openapi-generator/src/main/resources/haskell-servant/API.mustache index 5816f610671..400dee38f1d 100644 --- a/modules/openapi-generator/src/main/resources/haskell-servant/API.mustache +++ b/modules/openapi-generator/src/main/resources/haskell-servant/API.mustache @@ -61,7 +61,8 @@ import Servant.Client (ClientEnv, Scheme (Http), C mkClientEnv, parseBaseUrl) import Servant.Client.Core (baseUrlPort, baseUrlHost) import Servant.Client.Internal.HttpClient (ClientM (..)) -import Servant.Server (Handler (..)) +import Servant.Server (Handler (..)){{#serveStatic}} +import Servant.Server.StaticFiles (serveDirectoryFileServer){{/serveStatic}} import Web.FormUrlEncoded import Web.HttpApiData @@ -131,7 +132,8 @@ formatSeparatedQueryList char = T.intercalate (T.singleton char) . map toQueryPa type {{title}}API = {{#apis}}{{#operations}}{{#operation}}{{& vendorExtensions.x-routeType}} -- '{{operationId}}' route{{#hasMore}} :<|> {{/hasMore}}{{/operation}}{{/operations}}{{#hasMore}} - :<|> {{/hasMore}}{{/apis}} + :<|> {{/hasMore}}{{/apis}}{{#serveStatic}} + :<|> Raw {{/serveStatic}} {{/apiInfo}} @@ -183,7 +185,8 @@ create{{title}}Client = {{title}}Backend{..} where ({{#apis}}{{#operations}}{{#operation}}(coerce -> {{operationId}}){{#hasMore}} :<|> {{/hasMore}}{{/operation}}{{/operations}}{{#hasMore}} :<|> - {{/hasMore}}{{/apis}}) = client (Proxy :: Proxy {{title}}API) + {{/hasMore}}{{/apis}}{{#serveStatic}} :<|> + _{{/serveStatic}}) = client (Proxy :: Proxy {{title}}API) -- | Run requests in the {{title}}Client monad. run{{title}}Client :: Config -> {{title}}Client a -> ExceptT ClientError IO a @@ -234,5 +237,6 @@ run{{title}}MiddlewareServer Config{..} middleware backend = do serverFromBackend {{title}}Backend{..} = ({{#apis}}{{#operations}}{{#operation}}coerce {{operationId}}{{#hasMore}} :<|> {{/hasMore}}{{/operation}}{{/operations}}{{#hasMore}} :<|> - {{/hasMore}}{{/apis}}) + {{/hasMore}}{{/apis}}{{#serveStatic}} :<|> + serveDirectoryFileServer "static"{{/serveStatic}}) {{/apiInfo}} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellServantOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellServantOptionsProvider.java index f58c4e864ca..1ff66f0527b 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellServantOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellServantOptionsProvider.java @@ -19,6 +19,7 @@ package org.openapitools.codegen.options; import com.google.common.collect.ImmutableMap; import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.languages.HaskellServantCodegen; import java.util.Map; @@ -44,6 +45,7 @@ public class HaskellServantOptionsProvider implements OptionsProvider { .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE) .put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE) + .put(HaskellServantCodegen.PROP_SERVE_STATIC, HaskellServantCodegen.PROP_SERVE_STATIC_DEFAULT.toString()) .build(); } diff --git a/samples/server/petstore/haskell-servant/lib/OpenAPIPetstore/API.hs b/samples/server/petstore/haskell-servant/lib/OpenAPIPetstore/API.hs index 2f7f240a554..a6d82d94970 100644 --- a/samples/server/petstore/haskell-servant/lib/OpenAPIPetstore/API.hs +++ b/samples/server/petstore/haskell-servant/lib/OpenAPIPetstore/API.hs @@ -62,6 +62,7 @@ import Servant.Client (ClientEnv, Scheme (Http), C import Servant.Client.Core (baseUrlPort, baseUrlHost) import Servant.Client.Internal.HttpClient (ClientM (..)) import Servant.Server (Handler (..)) +import Servant.Server.StaticFiles (serveDirectoryFileServer) import Web.FormUrlEncoded import Web.HttpApiData @@ -156,6 +157,7 @@ type OpenAPIPetstoreAPI :<|> "user" :> "login" :> QueryParam "username" Text :> QueryParam "password" Text :> Verb 'GET 200 '[JSON] Text -- 'loginUser' route :<|> "user" :> "logout" :> Verb 'GET 200 '[JSON] () -- 'logoutUser' route :<|> "user" :> Capture "username" Text :> ReqBody '[JSON] User :> Verb 'PUT 200 '[JSON] () -- 'updateUser' route + :<|> Raw -- | Server or client configuration, specifying the host and port to query or serve on. @@ -237,7 +239,8 @@ createOpenAPIPetstoreClient = OpenAPIPetstoreBackend{..} (coerce -> getUserByName) :<|> (coerce -> loginUser) :<|> (coerce -> logoutUser) :<|> - (coerce -> updateUser)) = client (Proxy :: Proxy OpenAPIPetstoreAPI) + (coerce -> updateUser) :<|> + _) = client (Proxy :: Proxy OpenAPIPetstoreAPI) -- | Run requests in the OpenAPIPetstoreClient monad. runOpenAPIPetstoreClient :: Config -> OpenAPIPetstoreClient a -> ExceptT ClientError IO a @@ -303,4 +306,5 @@ runOpenAPIPetstoreMiddlewareServer Config{..} middleware backend = do coerce getUserByName :<|> coerce loginUser :<|> coerce logoutUser :<|> - coerce updateUser) + coerce updateUser :<|> + serveDirectoryFileServer "static")