Skip to content

Commit

Permalink
concord-server: allow custom top-level API endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
ibodrov committed Apr 19, 2024
1 parent 8ff13c3 commit dfb2a6f
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* =====
*/

import com.walmartlabs.concord.server.boot.resteasy.ApiDescriptor;
import com.walmartlabs.concord.server.cfg.ServerConfiguration;
import org.eclipse.jetty.ee8.nested.SessionHandler;
import org.eclipse.jetty.ee8.servlet.FilterHolder;
Expand All @@ -31,6 +32,7 @@
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -56,6 +58,7 @@ public class HttpServer {
public HttpServer(ServerConfiguration cfg,
Set<RequestErrorHandler> requestErrorHandlers,
Set<ServletContextListener> contextListeners,
Set<ApiDescriptor> apiDescriptors,
Set<HttpServlet> servlets,
Set<ServletHolder> servletHolders,
Set<Filter> filters,
Expand Down Expand Up @@ -119,6 +122,15 @@ public HttpServer(ServerConfiguration cfg,
contextHandler.addEventListener(listener);
});

// init all Resteasy endpoints
apiDescriptors.forEach(api -> {
ServletHolder holder = new ServletHolder(HttpServletDispatcher.class);
for (String pathSpec : api.paths()) {
log.info("Serving API endpoints on @ {}", pathSpec);
contextHandler.addServlet(holder, pathSpec);
}
});

// init all @WebServlets
servlets.stream().sorted(byPriority()).forEachOrdered(servlet -> {
WebServlet annotation = servlet.getClass().getAnnotation(WebServlet.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.walmartlabs.concord.server.boot.resteasy;

/*-
* *****
* Concord
* -----
* Copyright (C) 2017 - 2024 Walmart Inc.
* -----
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =====
*/

/**
* Declares an API.
*/
public interface ApiDescriptor {

/**
* Path patterns of the API. E.g. {@code "/api/**"} or {@code "/events/foo"}.
*/
String[] paths();
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* *****
* Concord
* -----
* Copyright (C) 2017 - 2023 Walmart Inc.
* Copyright (C) 2017 - 2024 Walmart Inc.
* -----
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,18 +20,13 @@
* =====
*/

import org.eclipse.jetty.ee8.servlet.ServletHolder;
import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher;
public class ConcordApiDescriptor implements ApiDescriptor {

import javax.servlet.annotation.WebServlet;

@WebServlet({
"/api/*",
"/events/github/*"
})
public class ResteasyServletHolder extends ServletHolder {

public ResteasyServletHolder() {
super(HttpServletDispatcher.class);
@Override
public String[] paths() {
return new String[]{
"/api/*",
"/events/github/*"
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,12 @@
import static com.google.inject.Scopes.SINGLETON;
import static com.google.inject.multibindings.Multibinder.newSetBinder;
import static com.walmartlabs.concord.server.Utils.bindExceptionMapper;
import static com.walmartlabs.concord.server.Utils.bindServletHolder;

public class ResteasyModule implements Module {

@Override
public void configure(Binder binder) {
bindServletHolder(binder, ResteasyServletHolder.class);
newSetBinder(binder, ApiDescriptor.class).addBinding().to(ConcordApiDescriptor.class);

newSetBinder(binder, ServletContextListener.class).addBinding().to(ResteasyListener.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.util.WebUtils;

import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.stream.Stream;

/**
* Implementation of {@link org.apache.shiro.mgt.RememberMeManager}. Uses the DB to store session data.
Expand All @@ -51,7 +54,7 @@ public ConcordRememberMeManager(RememberMeConfiguration cfg) {
setCipherKey(cipherKey);
}

int maxAge = (int)cfg.getRememberMeMaxAge().getSeconds();
int maxAge = (int) cfg.getRememberMeMaxAge().getSeconds();
getCookie().setMaxAge(maxAge);

setSerializer(new PrincipalCollectionSerializer());
Expand All @@ -74,6 +77,18 @@ protected void rememberIdentity(Subject subject, PrincipalCollection src) {
super.rememberIdentity(subject, dst);
}

@Override
protected void forgetIdentity(Subject subject) {
if (WebUtils.isHttp(subject)) {
HttpServletRequest request = WebUtils.getHttpRequest(subject);
var rememberMeCookieName = getCookie().getName();
if (Stream.of(request.getCookies())
.anyMatch(cookie -> cookie.getName().equals(rememberMeCookieName))) {
super.forgetIdentity(subject);
}
}
}

private static class PrincipalCollectionSerializer implements Serializer<PrincipalCollection> {
@Override
public byte[] serialize(PrincipalCollection principalCollection) throws SerializationException {
Expand Down

0 comments on commit dfb2a6f

Please sign in to comment.