Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static Content with quarkus.http-root-context #19492

Closed
brentcrammond opened this issue Aug 19, 2021 · 10 comments · Fixed by #19501
Closed

Static Content with quarkus.http-root-context #19492

brentcrammond opened this issue Aug 19, 2021 · 10 comments · Fixed by #19501
Labels
area/resteasy-classic kind/bug Something isn't working
Milestone

Comments

@brentcrammond
Copy link

brentcrammond commented Aug 19, 2021

Describe the bug

If I set the quarkus.http-root-context static content does not always work.

I have a Vue front end that is included from the src/main/ui directory.

When I run it from the command line

java -jar target/quarkus-app/quarkus-run.jar

The jax-rs call works but the static content does not.

Expected behavior

quarkus.http-root-context = /testing/

Working:
http://127.0.0.1:8080/testing/hello

Not working:
http://127.0.0.1:8080/testing/
http://127.0.0.1:8080/testing/index.html

These should show the web page from the UI directory, note if I don't have the quarkus.http-root-context set it works correctly.

Actual behavior

It should be displaying the index.html build from the ui directory, instead I get the error.

RESTEASY003210: Could not find resource for full path: http://127.0.0.1:8080/testing/index.html

How to Reproduce?

test-me.zip

maven clean package
java -jar target/quarkus-app/quarkus-run.jar

Browser to
http://127.0.0.1:8080/testing/index.html

Which will fail.

Output of uname -a or ver

Darwin xxxxxx 20.6.0 Darwin Kernel Version 20.6.0: Wed Jun 23 00:26:27 PDT 2021; root:xnu-7195.141.2~5/RELEASE_ARM64_T8101 arm64

Output of java -version

openjdk version "11.0.11" 2021-04-20 LTS OpenJDK Runtime Environment Zulu11.48+21-CA (build 11.0.11+9-LTS) OpenJDK 64-Bit Server VM Zulu11.48+21-CA (build 11.0.11+9-LTS, mixed mode)

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.1.2

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d) Maven home: /Users/brent/.m2/wrapper/dists/apache-maven-3.8.1-bin/2l5mhf2pq2clrde7f7qp1rdt5m/apache-maven-3.8.1 Java version: 11.0.11, vendor: Azul Systems, Inc., runtime: /Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home Default locale: en_NZ, platform encoding: UTF-8 OS name: "mac os x", version: "11.5.2", arch: "aarch64", family: "mac"

Additional information

It uses the following maven plugin to copy the UI into place, normally it would be a dist directory under ui build from VueJS, but I have simplified it down for this example.

  <plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <version>3.1.0</version>
    <executions>
      <execution>
        <id>copy-resources</id>
        <phase>validate</phase>
        <goals>
          <goal>copy-resources</goal>
        </goals>
        <configuration>
          <outputDirectory>${basedir}/target/classes/META-INF/resources</outputDirectory>
          <resources>
            <resource>
              <directory>src/main/ui</directory>
            </resource>
          </resources>
        </configuration>
      </execution>
    </executions>
  </plugin>

No response

@brentcrammond brentcrammond added the kind/bug Something isn't working label Aug 19, 2021
@gsmet
Copy link
Member

gsmet commented Aug 19, 2021

There is something fishy. For the record, the OP is talking about quarkus.http.root-path.

AFAICS, things are working in dev mode, I can get the index page by going to http://localhost:8080/testing/ but it's not working in prod mode when running the jar, RESTEasy takes the precedence somehow and is trying (and fails) to serve the resource.

@stuartwdouglas does it ring a bell?

@brentcrammond
Copy link
Author

brentcrammond commented Aug 19, 2021 via email

@brentcrammond
Copy link
Author

brentcrammond commented Aug 19, 2021 via email

@gsmet
Copy link
Member

gsmet commented Aug 19, 2021

Well, in any case, even if not serving the exact same file, serving the static file is working in dev mode but not in prod mode.

@brentcrammond
Copy link
Author

brentcrammond commented Aug 19, 2021 via email

@gsmet
Copy link
Member

gsmet commented Aug 19, 2021

It works if you remove the final slash of your root path:

quarkus.http.root-path=/testing

I'll have a closer look at what is happening...

gsmet added a commit to gsmet/quarkus that referenced this issue Aug 19, 2021
I think it's better to make sure it's always consistent. '/' is a bit of
a special case right now and not entirely consistent with the no slash
at the end rule but I think we can live with it.

Fixes quarkusio#19492
@gsmet
Copy link
Member

gsmet commented Aug 19, 2021

#19501 will hopefully fix it.

@brentcrammond
Copy link
Author

I just noticed that it is throwing an error when I take the / off the end of the configuration

was
quarkus.http.root-path=/testing/

changed too

quarkus.http.root-path=/testing

2021-08-19 22:05:45,432 ERROR [io.ver.ext.web.RoutingContext] (vert.x-eventloop-thread-9) Unhandled exception in router: java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.base/java.lang.String.substring(String.java:1841)
at io.quarkus.vertx.http.runtime.StaticResourcesRecorder.lambda$start$1(StaticResourcesRecorder.java:59)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1127)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:151)
at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:201)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:345)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:323)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1127)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:151)
at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:201)
at io.vertx.ext.web.impl.RouterImpl.handleContext(RouterImpl.java:236)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1127)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:151)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:133)
at io.vertx.ext.web.impl.RouterImpl.handle(RouterImpl.java:55)
at io.vertx.ext.web.impl.RouterImpl.handle(RouterImpl.java:37)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$10.handle(VertxHttpRecorder.java:437)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$10.handle(VertxHttpRecorder.java:434)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$1.handle(VertxHttpRecorder.java:151)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$1.handle(VertxHttpRecorder.java:133)
at io.vertx.core.http.impl.Http1xServerRequestHandler.handle(Http1xServerRequestHandler.java:67)
at io.vertx.core.http.impl.Http1xServerRequestHandler.handle(Http1xServerRequestHandler.java:30)
at io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:49)
at io.vertx.core.impl.DuplicatedContext.emit(DuplicatedContext.java:167)
at io.vertx.core.http.impl.Http1xServerConnection.handleMessage(Http1xServerConnection.java:145)
at io.vertx.core.net.impl.ConnectionBase.read(ConnectionBase.java:155)
at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:154)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
at io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandler.channelRead(WebSocketServerExtensionHandler.java:99)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.vertx.core.http.impl.Http1xUpgradeToH2CHandler.channelRead(Http1xUpgradeToH2CHandler.java:116)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.vertx.core.http.impl.Http1xOrH2CHandler.end(Http1xOrH2CHandler.java:61)
at io.vertx.core.http.impl.Http1xOrH2CHandler.channelRead(Http1xOrH2CHandler.java:38)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:829)

@gsmet
Copy link
Member

gsmet commented Aug 19, 2021

Weird I don't have that with the main branch. I'll dig a bit further.

gsmet added a commit to gsmet/quarkus that referenced this issue Aug 19, 2021
Make sure the quarkus.http.root-path always starts and ends with a '/'
so that we don't have any risk of having logic working with '/test' and
not with '/test/'.

Fixes quarkusio#19492
@gsmet
Copy link
Member

gsmet commented Aug 19, 2021

Ok, I don't know why it's working with main and not with the version you are using but I slightly adjusted the logic in my PR given your feedback.

gsmet added a commit to gsmet/quarkus that referenced this issue Aug 19, 2021
…config level

Make sure both paths always start and end with a '/'
so that we don't have any risk of having logic working with '/test' and
not with '/test/'.

Also simplify a few things thanks to that.

Fixes quarkusio#19492
gsmet added a commit to gsmet/quarkus that referenced this issue Aug 23, 2021
…config level

Make sure both paths always start and end with a '/'
so that we don't have any risk of having logic working with '/test' and
not with '/test/'.

Adjust the servlet context path too.

Also simplify a few things thanks to that.

Fixes quarkusio#19492
gsmet added a commit to gsmet/quarkus that referenced this issue Aug 23, 2021
…config level

Make sure both paths always start and end with a '/'
so that we don't have any risk of having logic working with '/test' and
not with '/test/'.

Adjust the servlet context path too.

Also simplify a few things thanks to that.

Fixes quarkusio#19492
@quarkus-bot quarkus-bot bot added this to the 2.3 - main milestone Aug 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/resteasy-classic kind/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants