简体   繁体   中英

Tapestry page and API

I have an application which offers a frontend but should also allow API calls (modifying the application). Therefore I have an Index class which redirects to the frontend when the context is not similar to an API call url and otherwise doesn't redirect. However, the api call doesn't reach the Jersey API handler but simply displays the default layout.

In my Index class I have:

Object onActivate(EventContext context) {
    if (context.getCount() < 2)
        return WorkspaceOverview.class;
    String first = context.get(String.class, 0);
    String second = context.get(String.class, 1);
    return "api".equalsIgnoreCase(first) &&
            Arrays.stream(allowedApiCalls).anyMatch(s -> s.equalsIgnoreCase(second))
            ? null
            : WorkspaceOverview.class;
}

In the API class I have (with different namings but generally the same):

@Path("/api")
@Api(description = "description")
@Generated(value = "io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2018-10-29T15:10:52.958Z")
public class Api {
    private ApiService getDelegate() {
        return (ApiService) Bootstrap.getRegistry().getService(ApiService.class);
    }

    @PUT
    @Path("/request")
    @ApiOperation(value = "handles", notes = "notes", response = Void.class, authorizations = {
            @Authorization(value = "basicAuth") }, tags = {})
    @ApiResponses(value = {    
            @ApiResponse(code = 200, message = "The request update was successful", response = Void.class),
            @ApiResponse(code = 400, message = "An unknown error occurred", response = Void.class),
            @ApiResponse(code = 401, message = "Authentication information is missing or invalid", response = Void.class),
            @ApiResponse(code = 404, message = "The request doesn't exist", response = Void.class) })
    public Response request(
            @ApiParam(value = "The of the request", required = true) @QueryParam("id") Long id,
            @ApiParam(value = "value", required = true, allowableValues = "A, B, C") @QueryParam("value") String value,
            @Context SecurityContext securityContext, @Context HttpHeaders headers, @Context HttpServletRequest request) throws NotFoundException {
        String authorizationHeader = headers.getHeaderString("Authorization");
        String requestHost = headers.getHeaderString("Host");
        String remoteHost = request.getRemoteHost();
        return getDelegate().handleRequest(id, value, securityContext, authorizationHeader, requestHost, remoteHost);
    }
}

And in my pom (drastically shortened):

<project
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">

  <artifactId>Project</artifactId>

  <packaging>war</packaging>

  <name>Project</name>

    <dependency>
      <groupId>org.apache.tapestry</groupId>
      <artifactId>tapestry-core</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.tapestry</groupId>
      <artifactId>tapestry-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.tapestry</groupId>
      <artifactId>tapestry-javadoc</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.glassfish</groupId>
      <artifactId>javax.json</artifactId>
    </dependency>
    <dependency>
      <groupId>io.swagger</groupId>
      <artifactId>swagger-jersey2-jaxrs</artifactId>
      <scope>compile</scope>
      <version>${swagger-core-version}</version>
    </dependency>
    <dependency>
      <groupId>io.swagger</groupId>
      <artifactId>swagger-annotations</artifactId>
      <version>${swagger-core-version}</version>
    </dependency>
    <dependency>
      <groupId>com.squareup.okhttp</groupId>
      <artifactId>okhttp</artifactId>
      <version>${okhttp-version}</version>
    </dependency>
    <dependency>
      <groupId>com.squareup.okhttp</groupId>
      <artifactId>logging-interceptor</artifactId>
      <version>${okhttp-version}</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.containers</groupId>
      <artifactId>jersey-container-servlet-core</artifactId>
      <version>${jersey2-version}</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.media</groupId>
      <artifactId>jersey-media-multipart</artifactId>
      <version>${jersey2-version}</version>
    </dependency>
    <dependency>
        <groupId>de.mkammerer</groupId>
        <artifactId>argon2-jvm</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.tapestry</groupId>
        <artifactId>tapestry-upload</artifactId>
        <version>${tapestry-release-version}</version>
    </dependency>

    <dependency>
      <groupId>org.apache.tapestry</groupId>
      <artifactId>tapestry-csrf-protection</artifactId>
      <version>${tapestry-csrf.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.tapestry</groupId>
      <artifactId>tapestry-kaptcha</artifactId>
      <version>${tapestry-release-version}</version>
    </dependency>
  </dependencies>

  <build>
    <finalName>Project</finalName>


  <properties>
    <jetty-maven-version>9.2.21.v20170120</jetty-maven-version>
    <tapestry-release-version>5.4.3</tapestry-release-version>
    <servlet-api-release-version>2.5</servlet-api-release-version>
    <testng-release-version>5.14.10</testng-release-version>
    <tapestry-security-version>0.6.6</tapestry-security-version>
    <swagger-core-version>1.5.15</swagger-core-version>
    <okhttp-version>2.7.5</okhttp-version>
    <gson-version>2.8.1</gson-version>
    <jersey2-version>2.22.2</jersey2-version>
    <maven.compiler.target>1.7</maven.compiler.target>
    <maven.compiler.source>1.7</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <tapestry-csrf.version>1.2.0.RELEASE</tapestry-csrf.version>
  </properties>
</project>

And the web.xml :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
        PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>    
    <context-param>
        <!-- The only significant configuration for Tapestry 5, this informs Tapestry of where to look for pages, components and mixins. -->
        <param-name>tapestry.app-package</param-name>
        <param-value>the.package.to.the.application</param-value>
    </context-param>
    <context-param>
        <param-name>tapestry.secure-enabled</param-name>
        <param-value>false</param-value>
    </context-param>

    <filter>
        <filter-name>ServletFilter</filter-name>
        <filter-class>the.package.of.the.filter.Filter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ServletFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>app</filter-name>
        <filter-class>org.apache.tapestry5.TapestryFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>app</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>
             the.package.of.the.listener.Listener
        </listener-class>
    </listener>

    <session-config>
      <tracking-mode>COOKIE</tracking-mode>
      <session-timeout>-1</session-timeout>
    </session-config>

    <!--API-->
    <servlet>
        <servlet-name>jersey</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>
                io.swagger.jaxrs.listing,
                io.swagger.sample.resource,
                the.package.to.the.api
            </param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.provider.classnames</param-name>
            <param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.wadl.disableWadl</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet>
        <servlet-name>Jersey2Config</servlet-name>
        <servlet-class>io.swagger.jersey.config.JerseyJaxrsConfig</servlet-class>
        <init-param>
            <param-name>api.version</param-name>
            <param-value>1.0.0</param-value>
        </init-param>
        <init-param>
            <param-name>swagger.api.title</param-name>
            <param-value>Swagger Server</param-value>
        </init-param>
        <init-param>
            <param-name>swagger.api.basepath</param-name>
            <param-value>https://localhost</param-value>
        </init-param>

        <load-on-startup>2</load-on-startup>
    </servlet>

    <servlet>
        <servlet-name>Bootstrap</servlet-name>
        <servlet-class>the.package.to.the.bootstrap.Bootstrap</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Bootstrap</servlet-name>
        <url-pattern>the.package.to.the.api.*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>jersey</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>ApiOriginFilter</filter-name>
        <filter-class>the.package.of.the.filter.Filter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ApiOriginFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

An example request would be:

curl -X PUT "localhost:8080/api/request?id=0&vaue=A" -H  "accept: application/json" -H  "authorization: Basic dXNlcjoxMjM0d" -k -v

But the result is always 200 with the html code of the DefaultLayout page.

If there's some minor mistake in the source code which would cause a comipilation error let me know, I had to modify the code not to reveal any secrets.

I think that's all relevant files, if you need more information, let me know in the comments. I'm sorry for not being able to provide a minimal, working example, but I simply don't know which files / parts of code are relevant.

Looks like the problem is in your <url-pattern>/*</url-pattern> -- they all watch the same pattern, so the first wins.

If all your API endpoints live under /api/* then update URL pattern accordingly, and move it before Tapestry filter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM