Hello,
For my use case, I would need java-httpbin to support handling requests on non-root paths, not only on the root path.
For example, for the /headers endpoint, we are currently forced to call http://127.0.0.1:8080/headers, whereas in my case I would need to call http://127.0.0.1:8080/some/other/path/headers (which returns 501 Not Implemented).
I thought of three possible options. Please let me know your thoughts, or if there is another option I may have missed.
Thank you!
Option 1: Custom HttpBinHandler
As mentioned in #15, I could indeed implement my own HttpBinHandler, but it would mostly be copy-and-paste work.
Since I would need to keep my implementation in sync with future changes in java-httpbin, this solution is neither ideal nor future-proof.
Option 2: Modify HttpBinHandler to support non-root paths
Modify HttpBinHandler so that it also handles non-root paths by default.
Not sure it is a valid approach as it seems to be a breaking change.
// HttpBinHandler
if (method.equals("GET") && uri.equals("/headers")) // Current implementation
if (method.equals("GET") && uri.endsWith("/headers")) // Proposed implementation: "endsWith" instead of "equals"
Option 3: Refactor HttpBinHandler to make it easier to extend/override
Instead of having a large if / else if / else block in a single method, perhaps a List<HttpBinRoute> could be introduced and iterated until a matching route is found.
This would make it easy to:
- Extend existing routes to adjust matching logic or behavior
- Add custom routes and behavior that are not provided by java-httpbin
It requires a bit more work, but it is also the most flexible approach. I would be glad to help 😊.
/**
* HttpBinHandler
*/
private List<HttpBinRoute> customRoutes = new ArrayList<>(); // mutable with some addCustomRoute(HttpBinRoute) method
private List<HttpBinRoute> defaultRoutes = /* default routes */;
private void handleHelper(Request baseRequest, HttpServletRequest request,
HttpServletResponse servletResponse, InputStream is,
OutputStream os) throws IOException {
if(!handleRoutes(customRoutes, baseRequest, request, servletResponse, is, os)) { // Try first to handle request with custom routes...
handleRoutes(defaultRoutes , baseRequest, request, servletResponse, is, os); // ... fallback to default routes otherwise
}
}
private boolean handleRoutes(List<HttpBinRoute> routes, Request baseRequest, HttpServletRequest request,
HttpServletResponse servletResponse, InputStream is,
OutputStream os) throws IOException {
// try
for(var route : routes) {
if(route.matches(request)) {
route.handle(baseRequest, request, servletResponse, is, os);
return true;
}
}
// catch JSONException
return false;
}
// ------------------------------------------------------------------------------
/**
* New interface
*/
public interface HttpBinRoute {
boolean matches(Request request);
void handle(Request baseRequest, HttpServletRequest request,
HttpServletResponse servletResponse, InputStream is,
OutputStream os) throws IOException;
}
/**
* Default implementation from java-httpbin.
* One implementation for each route handled by java-httpbin: HeadersRoute, GetRoute, PostRoute, IpRoute, etc.
*/
public class HeadersRoute implements HttpBinRoute {
public boolean matches(Request request) {
return request.getMethod().equals("GET") && request.getRequestURI().equals("/headers");
}
public void handle(...) throw IOException, JSONException {
// default implementation from HttpBinHandler
}
}
// ------------------------------------------------------------------------------
/**
* Custom implementation that only overrides the "matches" method.
*/
public class MyCustomHeadersRoute extends HeadersRoute {
@Override
public boolean matches(Request request) {
return request.getMethod().equals("GET") && request.getRequestURI().endsWith("/headers");
}
}
var handler = new HttpBinHandler();
handler.addCustomRoute(new MyCustomHeadersRoute());
var httpBin = new HttpBin( uri, handler );
httpBin.start();
Hello,
For my use case, I would need java-httpbin to support handling requests on non-root paths, not only on the root path.
For example, for the
/headersendpoint, we are currently forced to callhttp://127.0.0.1:8080/headers, whereas in my case I would need to callhttp://127.0.0.1:8080/some/other/path/headers(which returns501 Not Implemented).I thought of three possible options. Please let me know your thoughts, or if there is another option I may have missed.
Thank you!
Option 1: Custom
HttpBinHandlerAs mentioned in #15, I could indeed implement my own
HttpBinHandler, but it would mostly be copy-and-paste work.Since I would need to keep my implementation in sync with future changes in java-httpbin, this solution is neither ideal nor future-proof.
Option 2: Modify
HttpBinHandlerto support non-root pathsModify
HttpBinHandlerso that it also handles non-root paths by default.Not sure it is a valid approach as it seems to be a breaking change.
Option 3: Refactor
HttpBinHandlerto make it easier to extend/overrideInstead of having a large
if / else if / elseblock in a single method, perhaps aList<HttpBinRoute>could be introduced and iterated until a matching route is found.This would make it easy to:
It requires a bit more work, but it is also the most flexible approach. I would be glad to help 😊.