Dropwizard 0.8.0: serve static assets from / - path

I want my server to serve the static html files from /. Furthermore, css and js files should be served from /css respectively, /js. All json data should be accessible at /api.
However, I get a 404 for http://localhost:8080/ or any other path.
I use the following setting in the configuration file:
server:
type: simple
rootPath: /api/*
The application.initialize method looks like this:
#Override
public void initialize(io.dropwizard.setup.Bootstrap<MyConfiguration> bootstrap) {
bootstrap.addBundle(new AssetsBundle("/assets/css", "/css", null, "css"));
bootstrap.addBundle(new AssetsBundle("/assets/js", "/js", null, "js"));
bootstrap.addBundle(new AssetsBundle("/assets/pages", "/", "index.html", "html"));
}

I've just had to work through a similar problem (The documentation isn't the clearest, although with hindsight I guess most of the information is there somewhere), which I've resolved by setting both the applicationContextPath and the rootPath in my application config:
server:
type: simple
rootPath: /api/*
applicationContextPath: /
The default value for applicationContextPath is "/application" in a simple server, so your complete root-path would have been "/application/api/*". If you don't need to use the simple server, you could alternatively use the default server, which has the applicationContextPath set to "/" by default:
server:
rootPath: /api/*

Related

How the serve static html files with vaadin router

I have te following route configuration in my hilla app
router.setRoutes([
{path: '/', component: 'home-view'},
]);
this is works, but I need to publish some static html files. Not sure where to put the files and how to configure router to make them accessible with URL like /myfile.html?
already tried to put them in /frontend folder and add route, but does not work but creates a loop
{
path: '(.*)\.html',
action: (ctx, commands) => {
window.location.pathname = ctx.pathname;
}
}
Found it here How do I deliver static html pages with vaadin router (client side)?
The server is a Spring Boot server so any file you put inside src/main/resources/META-INF/resources is made available, e.g. if you create src/main/resources/META-INF/resources/myfile.html then you can access it as http://localhost:8080/myfile.html.
If you are just loading a static HTML page there is no need to configure the router for it. For a link you can add router-ignore so that router will not try to intercept it, e.g. `"

Springfox Swagger UI behind reverse proxy

I have configured a Spring Boot application with Swagger API documentation and configured Swagger UI.
I also run my backend application behind a reverse proxy that maps all requests from host:port/api to backend_host:port/, when running locally on localhost I map localhost:8082/api. In production a similar mapping is applied.
When I open the Swagger UI from localhost:8082/api/swagger-ui.html it shows the following lines below the title:
[ Base URL: localhost:8080 ]
http://localhost:8082/api/v2/api-docs
When I invoke any rest operation swagger always tries to perform it against localhost:8080 which then fails due to the same origin policy.
I am aware of using pathProvider but it only affects the base URL's path part, not the domain and port. So I can only use it to change the base URL to localhost:8080/api but I would need it to change to localhost:8082/api. Is there a way to set the host dynamically to the current host and port that is active in the browser?
.pathProvider (new RelativePathProvider (servletContext) {
#Override
public String getApplicationBasePath() {
return "/api";
}
})
In my case with a spring-boot:2.2.6 application with springdoc-openapi-ui:1.3.0 (that also has embedded the swagger UI), I solved the proxy problem setting the server URL in this way:
#Configuration
public class OpenApiConfig {
#Value("${server}")
private String url;
#Bean
#Profile("prod")
public OpenAPI customConfiguration() {
return new OpenAPI()
.servers(Collections
.singletonList(new Server().url(url))) //real public URL
.components(new Components())
.info(new Info().title("Dummy API Docs")
.description("Dummy REST API documentation"));
}
}
This change is reflected in the contract (https://real-domain.com/api-docs):
And in the Swagger UI (https://real-domain.com/swagger-ui/index.html?configUrl=/api-docs/swagger-config)
I think in your case you need to configure your proxy to set HTTP Header
(which will be forwarded to your target backend)
to "notify" Swagger endpoints to return custom URL in /apidocs endpoint.
Please configure proxy to set header X-Forwarded-Host to value from Host request header
Explanation:
In your browser when you will visit a url eg. https://my.domain.com/api/swagger-ui.html
the proxy should create and forward header X-Forwarded-Host: my.endpoint.com
to your backend localhost:8082/api/swagger-ui.html
-> so the Swagger /apidocs enpoint could take this header into consideration in response JSON.
My own case - in Microsoft IIS:
I needed to configure Microsoft IIS to serve Swagger IU from Apache Tomcat on 8080 port on HTTPS domain,
so I needed to have following configuration:
<serverVariables>
<set name="HTTP_X_FORWARDED_HOST" value=“{HTTP_HOST}” />
<set name="HTTP_X_FORWARDED_PROTO" value="https" />
</serverVariables>
JuanMorenos answer helped me, however, if anyone is using Springboot and annotations with OpenAPI you can define the URL in your main class
#SpringBootApplication
#OpenAPIDefinition(info = #Info(
version = "2.0",
title = "Swagger - My application",
description = "A description of the application"),
servers = #Server(
url = "http://yourhost:yourport",
description = "A description of the Server "
))

How to configure create-react-pwa with nested homepage (localhost/app)

I create an app by create-react-pwa(CRP) tool and I deploy the app to a local IIS root path. Then I open Chrome at localhost. Everything works great, even Service worker makes its job, fetches and caches app bundle and other resources. In dev tool, I click on Add to homescreen button in Application tab and a shortcut is added.
There is a problem when I change the root path to a subfolder (localhost/myapp). Of course, I change CRP settings and edit homepage in the package.json and manifest.json
//package.json
"homepage" : "/myapp"
//manifest.json
"start_url": "/myapp/",
Then I build the app and edit a path to service-worker in index.html
<script>
"serviceWorker" in navigator && window.addEventListener("load", function () {
navigator.serviceWorker.register("/myapp/service-worker.js")
})
</script>
I deploy this build to IIS subfolder named "/myapp" and try to inspect result in Chrome. Everything works well, service-worker works. But when I try to Add to homescreen it fails. Chrome display the error bellow:
Site cannot be installed: no matching service worker detected. You may need to reload the page, or check that the service worker for the current page also controls the start URL from the manifest
Please, has someone idea what is wrong?
Build structure:
/wwwroot
/myapp
/static
/index.html
/manifest.json
/service-worker.js
/ etc...
You seem to have done everything correctly except one thing - not defining the scope of the service worker while registering. So there are two things you can try out:
1.Try explicitly adding the scope of the service worker while registration. Before making bigger efforts as described in option 2, check if this works for you. CODE:
<script>
"serviceWorker" in navigator && window.addEventListener("load", function () {
navigator.serviceWorker.register('/myapp/service-worker.js', { scope : '/myapp/' })
})
</script>
2.A full proof way would be this one. Since you are using IIS, you can make changes to your web.config file to add the Service-Worker-Allowed Http header to the response of your service worker file. CODE:
<location path="/myapp/service-worker.js">
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Service-Worker-Allowed" value="/" />
</customHeaders>
</httpProtocol>
</system.webServer>
</location>
and then just define the scope as {scope : '/'} while registering your service worker. This way irrespective of your project structure or placement of your service worker, it should work. Basically what you are doing now is that you are adding "Service-Worker-Allowed" header in HTTP response to the service worker's script resource request. This answer is inspired from the example 10 in the service worker's spec link above.
We were able to get this running on a tomcat server. We had to ensure that
1) The manifest.json, service-worker.js and the index.html reside in WEB-INF directory.
2) Set up a request mapping like to ensure that the manifest and service-worker are returned from the proper location
#RequestMapping(value = "/manifest.json", method = RequestMethod.GET)
public #ResponseBody InternalResourceView manifest() throws IOException {
return new InternalResourceView("/WEB-INF/manifest.json");
}
#RequestMapping(value = "/service-worker.js", method = RequestMethod.GET)
public #ResponseBody InternalResourceView serviceWorker() throws IOException {
return new InternalResourceView("/WEB-INF/service-worker.js");
}
3) We placed the assets from the build script inside resources/static/ directory and made sure that the resources to cache were supplied with proper names, like so, in the service-worker.js
const BASE_STATIC_URLS = [
'.',
'index.html',
'offline.html',
'/myapp/static/js/0.16823424.chunk.js'
];

Externalized Grails 3 Spring Security Config

I am working on externalizing the .YML file in Grails 3.x. The code to make this work, is as follows:
In my Application.groovy, I am implementing the setEnviroment method form the EnvironmentAware interface.
#Override
void setEnvironment(Environment environment) {
try {
String configPath = System.properties["local.config.location"]
def ymlConfig = new File(configPath)
Resource resourceConfig = new FileSystemResource(ymlConfig)
YamlPropertiesFactoryBean ypfb = new YamlPropertiesFactoryBean()
ypfb.setResources(resourceConfig)
ypfb.afterPropertiesSet()
Properties properties = ypfb.getObject()
environment.propertySources.addFirst(new PropertiesPropertySource("local.config.location", properties))
} catch (Exception e) {
log.error("unable to load the external configuration file", e)
}
}
I have edited the bootRun task in the build to this:
bootRun {
jvmArgs = ['-Dlocal.config.location=external-config.yml']
}
When printing out the values in the setEnvironment method, the properties are indeed being read and added from the loaded object.
Now, for the fun part. When I add this code to my original application.yml file:
---
grails:
plugin:
springsecurity:
securityConfigType: 'InterceptUrlMap'
interceptUrlMap: [
{pattern: '/**', access: ['permitAll']}
]
providerNames: ['ldapAuthProvider', 'anonymousAuthenticationProvider']
ldap:
context:
managerDn: 'uid=admin,ou=system'
managerPassword: 'secret'
server: 'ldap://localhost:10389'
authorities:
groupSearchBase: 'ou=Groups,dc=aye,dc=com'
retreiveGroupRoles: true
retreiveDatabaseRoles: false
groupSearchFilter: 'member={0}'
search:
base: 'ou=Users,dc=aye,dc=com'
password:
algoritham: 'SHA-256'
---
Everything works just fine. When I cut and paste it out into the external yml file, I get this beautiful error in Firefox.
I can tell that the configuration is correct in the provided code, as I can add more roles and filters, and everything works just fine when in original application.yml file. It is only when reading from the external file does this fail. If I remove the security code from both .yml files, .ofc, my page looks strange but the firefox error disappears.
Has anyone got an idea as to why this can be the case?
One thing you can attempt to test if it will work, is rename your external-config.yml file to application.yml. I believe that the default name should be application, unless otherwise specified.
This article here shows a good example of its correct use
When you do that, try to read the properties in one of your classes, to make sure that the yml files are merging. You can read these properties using a command like this:
grailsApplication.config.getProperty("grails.plugin.springsecurity.securityConfigType")
Or, you can print out all of them, using the Holders utility
def config = Holders.config

Kestrel on AspNet vNext doesnt serve index page under /

I need to be able to serve my 'index.html', under the default url /, using Kestrel web server. Right now I'm only able to access my static files with the full path i.e /index.html
Again this works perfectly on VisualStudio, the context is OSX with Kestrel
This is my Startup.cs
public void ConfigureServices(DI.IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles();
app.UseMvc();
}
The solution I have so far, is to do a redirect inside a HomeController. But this is plain ugly, I'm trying to serve an static html file, which I honestly don't want it to be handled by my Application, if possible served directly from Kestrel.
You need to enable the DefaultFilesMiddleware using UseDefaultFiles() and place it before the call to UseStaticFiles():
app.UseDefaultFiles();
app.UseStaticFiles();
If you don't specify otherwise, the middleware uses the DefaultFilesOptions by default, which means this list of default file names will be used:
default.htm
default.html
index.htm
index.html
See MSDN

Resources