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

JAX-RS fails with 400 Bad Request when query string contains _type param #19413

Closed
lmsurpre opened this issue Nov 19, 2021 · 3 comments · Fixed by #19421
Closed

JAX-RS fails with 400 Bad Request when query string contains _type param #19413

lmsurpre opened this issue Nov 19, 2021 · 3 comments · Fixed by #19421
Assignees
Labels
in:JAX-RS release bug This bug is present in a released version of Open Liberty release:22001 team:Wendigo West

Comments

@lmsurpre
Copy link

lmsurpre commented Nov 19, 2021

Describe the bug

Previously-working JAX-RS methods with the _type query parameter are now failing:

[INFO] [WARNING ] javax.ws.rs.BadRequestException: HTTP 400 Bad Request
[INFO]  at org.apache.cxf.jaxrs.utils.SpecExceptions.toBadRequestException(SpecExceptions.java:84)
[INFO]  at org.apache.cxf.jaxrs.utils.ExceptionUtils.toBadRequestException(ExceptionUtils.java:120)
[INFO]  at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:178)
[INFO]  at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:96)
[INFO]  at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
[INFO]  at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:123)
[INFO]  at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:277)
[INFO]  at com.ibm.ws.jaxrs20.endpoint.AbstractJaxRsWebEndpoint.invoke(AbstractJaxRsWebEndpoint.java:137)
[INFO]  at com.ibm.websphere.jaxrs.server.IBMRestServlet.handleRequest(IBMRestServlet.java:146)
[INFO]  at com.ibm.websphere.jaxrs.server.IBMRestServlet.doGet(IBMRestServlet.java:112)
[INFO]  at javax.servlet.http.HttpServlet.service(HttpServlet.java:686)
[INFO]  at com.ibm.websphere.jaxrs.server.IBMRestServlet.service(IBMRestServlet.java:96)
[INFO]  at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1258)
[INFO]  at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:746)
[INFO]  at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:443)
[INFO]  at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1227)
[INFO]  at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1011)
[INFO]  at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:75)
[INFO]  at com.ibm.ws.webcontainer40.servlet.CacheServletWrapper40.handleRequest(CacheServletWrapper40.java:85)
[INFO]  at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:938)
[INFO]  at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost$2.run(DynamicVirtualHost.java:279)
[INFO]  at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink$TaskWrapper.run(HttpDispatcherLink.java:1159)
[INFO]  at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink.wrapHandlerAndExecute(HttpDispatcherLink.java:428)
[INFO]  at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink.ready(HttpDispatcherLink.java:387)
[INFO]  at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:566)
[INFO]  at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.handleNewRequest(HttpInboundLink.java:500)
[INFO]  at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.processRequest(HttpInboundLink.java:360)
[INFO]  at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.ready(HttpInboundLink.java:327)
[INFO]  at com.ibm.ws.tcpchannel.internal.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:167)
[INFO]  at com.ibm.ws.tcpchannel.internal.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:75)
[INFO]  at com.ibm.ws.tcpchannel.internal.WorkQueueManager.requestComplete(WorkQueueManager.java:504)
[INFO]  at com.ibm.ws.tcpchannel.internal.WorkQueueManager.attemptIO(WorkQueueManager.java:574)
[INFO]  at com.ibm.ws.tcpchannel.internal.WorkQueueManager.workerRun(WorkQueueManager.java:958)
[INFO]  at com.ibm.ws.tcpchannel.internal.WorkQueueManager$Worker.run(WorkQueueManager.java:1047)
[INFO]  at com.ibm.ws.threading.internal.ExecutorServiceImpl$RunnableWrapper.run(ExecutorServiceImpl.java:238)
[INFO]  at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[INFO]  at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[INFO]  at java.base/java.lang.Thread.run(Thread.java:829)
[INFO] Caused by: java.lang.IllegalArgumentException: Media type separator is missing
[INFO]  at org.apache.cxf.jaxrs.impl.MediaTypeHeaderProvider.handleMediaTypeWithoutSubtype(MediaTypeHeaderProvider.java:191)
[INFO]  at org.apache.cxf.jaxrs.impl.MediaTypeHeaderProvider.internalValueOf(MediaTypeHeaderProvider.java:80)
[INFO]  at org.apache.cxf.jaxrs.impl.MediaTypeHeaderProvider.valueOf(MediaTypeHeaderProvider.java:66)
[INFO]  at org.apache.cxf.jaxrs.utils.JAXRSUtils.toMediaType(JAXRSUtils.java:1978)
[INFO]  at org.apache.cxf.jaxrs.utils.JAXRSUtils.parseMediaTypes(JAXRSUtils.java:1641)
[INFO]  at org.apache.cxf.jaxrs.utils.JAXRSUtils.sortMediaTypes(JAXRSUtils.java:1810)
[INFO]  at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:174)
[INFO]  ... 35 more

Steps to Reproduce

  1. git clone https://github.com/openliberty/guide-rest-intro.git
  2. modify line 45 of EndpointIT to include a query parameter with name _type
    WebTarget target = client.target(url + "system/properties" + "?_type=a");
    
  3. start the server and run the test

Expected behavior
The request should still work

Diagnostic information:

  • OpenLiberty Version: 21.0.0.11
  • Affected feature(s): jaxrs-2.1
  • Java Version:
openjdk version "11.0.13" 2021-10-19
OpenJDK Runtime Environment Temurin-11.0.13+8 (build 11.0.13+8)
OpenJDK 64-Bit Server VM Temurin-11.0.13+8 (build 11.0.13+8, mixed mode)
  • server.xml configuration (WITHOUT sensitive information like passwords)
<server description="Intro REST Guide Liberty server">
  <!-- tag::featureManager[] -->
  <featureManager>
      <feature>jaxrs-2.1</feature>
  </featureManager>
  <!-- end::featureManager[] -->

  <!-- tag::httpEndpoint[] -->
  <httpEndpoint httpPort="${default.http.port}" httpsPort="${default.https.port}"
                id="defaultHttpEndpoint" host="*" />
  <!-- end::httpEndpoint[] -->
  
  <!-- tag::webApplication[] -->
  <webApplication location="guide-rest-intro.war" contextRoot="${app.context.root}"/>
  <!-- end::webApplication[] -->
</server>

Additional context
Add any other context about the problem here.

@lmsurpre lmsurpre added the release bug This bug is present in a released version of Open Liberty label Nov 19, 2021
@lmsurpre
Copy link
Author

We found a workaround which is to set the org.apache.cxf.jaxrs.mediaTypeCheck.strict context property to false.
I found two ways to do that:

  1. via web.xml
    <servlet>
        <servlet-name>FHIRRestServlet</servlet-name>
        <servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>io.openliberty.guides.rest.SystemApplication</param-value>
        </init-param>
        <init-param>
            <param-name>org.apache.cxf.jaxrs.mediaTypeCheck.strict</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
  2. by overriding getProperties() in your JAXRS Application class
    public class SystemApplication extends Application {
        @Override
        public Map<String, Object> getProperties() {
            return Collections.singletonMap("org.apache.cxf.jaxrs.mediaTypeCheck.strict", false);
        }
    }
    

@WhiteCat22
Copy link
Member

Looks like this change was caused by setting the org.apache.cxf.jaxrs.mediaTypeCheck.strict property to true if the user doesn't set it in #18554

@andymc12
Copy link
Contributor

#18554 exposed an issue with the app. It is using the _type and _ctype query parameters, which are reserved parameters in CXF (see http://cxf.apache.org/docs/jax-rs.html#JAX-RS-Debugging ). These query parameters have the effect of re-setting the request's Accept and Content-Type headers, respectively. Thus, the request URI of url + "system/properties" + "?_type=a" (from the description comment) is effectively setting the Accept header's value to a, which is invalid - valid values for the Accept header would include things like text/plain, application/json, etc. - all requiring a slash.

#18554 enforces that Accept and Content-Type headers sent from the client are valid. Setting org.apache.cxf.jaxrs.mediaTypeCheck.strict=false works around this issue by allowing invalid Accept/Content-Type header values - and treating them as wildcards. This may not be desired in most cases.

Instead, applications should not use the _type/_ctype/etc. query parameters. But since that may not be possible for existing applications that were operating without strict media type checking, I think a better alternative would be to disable the CXF debug behavior for those query parameters. That will require a code change in Liberty.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in:JAX-RS release bug This bug is present in a released version of Open Liberty release:22001 team:Wendigo West
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants