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

feat[ServletAdapter]: Ability remove context path when get method name #11730

Closed
wants to merge 10 commits into from

Conversation

long76
Copy link

@long76 long76 commented Dec 9, 2024

Refs: #5066

Complex application may have many war-s and do not allow monopolize root context path(/). Add ability to remove context path(usual it's war name) from application server use @WebInitParam or just override getInitParameter for parameter GrpcServlet.REMOVE_CONTEXT_PATH

requestURI = contextPath + servletPath + pathInfo

https://stackoverflow.com/a/42706412

Copy link

linux-foundation-easycla bot commented Dec 9, 2024

CLA Signed

The committers listed above are authorized under a signed CLA.

@long76 long76 marked this pull request as draft December 9, 2024 15:02
@panchenko
Copy link
Contributor

Could you please describe the problem you are trying to solve?

@long76
Copy link
Author

long76 commented Dec 9, 2024

Could you please describe the problem you are trying to solve?

I use Wildfly 24 and need use non root context(/) for GRPC. I can use custom path for GRPC server? On GRPC clients like Insomnia and Postman i can't put localhost:8080/grpc-war in url. This MR allow use custom context for application servers like WildFly. If i will use HAProxy or something else for proxy i can get access for GRPC server on Wildfly 24 on GrpcServlet.

@panchenko
Copy link
Contributor

I can use custom path for GRPC server?

No.

Insomnia and Postman

They are not real clients, but UI tools to send arbitrary requests to server for development purposes.

@long76 long76 marked this pull request as ready for review December 11, 2024 17:20
@ejona86
Copy link
Member

ejona86 commented Dec 26, 2024

Yeah, there's not going to be clients that work with this. It sounds like you would get testing infrastructure running, but once you try to make real clients you're going to have problems.

@ejona86 ejona86 closed this Jan 13, 2025
@long76
Copy link
Author

long76 commented Jan 14, 2025

@ejona86 local fork works great on Wildfly 24, my patch do not break backward compatibility

@ejona86
Copy link
Member

ejona86 commented Jan 14, 2025

The server is irrelevant. We were saying the clients won't support this as gRPC doesn't support this.

@long76
Copy link
Author

long76 commented Jan 14, 2025

The server is irrelevant. We were saying the clients won't support this as gRPC doesn't support this.

This will work with proxy. Nginx > Wildfly > GRPCServlet works. I do not see limitations for support this for GRPCServlet.

@panchenko
Copy link
Contributor

@long76 Do you mean ngx_http_grpc_module ?
It does not support changing request path.

@long76
Copy link
Author

long76 commented Jan 14, 2025

@long76 Do you mean ngx_http_grpc_module ?
It does not support changing request path.

😏Just try this config for nginx:

server {
        server_name mygrpc-sever.com;
        listen 3000 http2;

        location / {
                rewrite ^(/.*)$ /grpc$1 break;
                grpc_pass grpcs://ip_or_domain_wildfly:443;
        }
}

P.S. i don't know it's bug or feature nginx but i glad this flexibility)

Copy link
Member

@ejona86 ejona86 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't REMOVE_CONTEXT_PATH mean that you must put the servlet under its own "folder" because it will need a wildcard for the full service/method. So where your app may be /app1, you'd then have to do something like /app1/grpc/* for the servlet so that the requested path is /app1/grpc/helloworld.Greeter/SayHello?

@@ -110,7 +111,8 @@ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOExc
* <p>Do not modify {@code req} and {@code resp} before or after calling this method. However,
* calling {@code resp.setBufferSize()} before invocation is allowed.
*/
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleting this breaks compatibility. If you have to modify the helloworld example (hard-coding a string no less!), then that clearly is API-breaking.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree that hard-coded string is bad but for now i dont found better solution, i need more time or you can suggest smth

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't follow the difficulty.

public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
  doPost(req.getRequestURI().substring(1), req, resp);
}

@@ -58,6 +59,16 @@ private static ServletAdapter loadServices(List<? extends BindableService> binda
return serverBuilder.buildServletAdapter();
}

private String getMethod(HttpServletRequest req) {
Boolean removeContextPath = Boolean.parseBoolean(getInitParameter(REMOVE_CONTEXT_PATH));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be done per-request. We should do this in init instead, right?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree, fix it soon

@@ -58,6 +59,16 @@ private static ServletAdapter loadServices(List<? extends BindableService> binda
return serverBuilder.buildServletAdapter();
}

private String getMethod(HttpServletRequest req) {
Boolean removeContextPath = Boolean.parseBoolean(getInitParameter(REMOVE_CONTEXT_PATH));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/Boolean/boolean/

String method = req.getRequestURI();
if (removeContextPath) {
// remove context path used in application server
method = method.substring(req.getContextPath().length());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this mostly the same as req.getPathInfo()? I wouldn't expect to need to do any string manipulation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, at first I thought the same thing. only getContextPath() needed. see https://coderanch.com/t/610432/certification/getContextPath-getServletPath-getPathInfo

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, you are making it relative to the deployment.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah)

@long76
Copy link
Author

long76 commented Jan 14, 2025

Doesn't REMOVE_CONTEXT_PATH mean that you must put the servlet under its own "folder" because it will need a wildcard for the full service/method. So where your app may be /app1, you'd then have to do something like /app1/grpc/* for the servlet so that the requested path is /app1/grpc/helloworld.Greeter/SayHello?

in our case we create dedicated grpc.war for it with root path /grpc and for everything to work need just remove contextPath

@long76
Copy link
Author

long76 commented Jan 14, 2025

new pull #11825

@panchenko
Copy link
Contributor

panchenko commented Jan 14, 2025

@long76 Have you considered name-based virtual hosting? and then deploy this code as ROOT.war in the "mygrpc" host.
So it can work even without nginx.

@long76
Copy link
Author

long76 commented Jan 15, 2025

@long76 Have you considered name-based virtual hosting? and then deploy this code as ROOT.war in the "mygrpc" host. So it can work even without nginx.

yeah, but we need our business logic from our app. we use ejb for access data from other wars.

@panchenko
Copy link
Contributor

@long76 There is also an "enterprise" way - you could use a servlet filter.

@long76
Copy link
Author

long76 commented Jan 15, 2025

@long76 There is also an "enterprise" way - you could use a servlet filter.

yeah but it doesn't work) it's was first that i try) maybe i make mistake somewhere

@panchenko
Copy link
Contributor

@long76 it seems like in your gRPC servlet class in doPost you can create a wrapper and pass it further

new HttpServletRequestWrapper(req) {
    @Override
    public String getRequestURI() {
        return super.getRequestURI().replaceFirst("^/grpc", "");
    }
};

As your setup does not quite match the current state of gRPC- not clear if the related changes should be in the library.

@long76
Copy link
Author

long76 commented Jan 17, 2025

@long76 it seems like in your gRPC servlet class in doPost you can create a wrapper and pass it further

new HttpServletRequestWrapper(req) {
    @Override
    public String getRequestURI() {
        return super.getRequestURI().replaceFirst("^/grpc", "");
    }
};

As your setup does not quite match the current state of gRPC- not clear if the related changes should be in the library.

Yeah, but no)

'doPost(HttpServletRequest, HttpServletResponse)' cannot override 'doPost(HttpServletRequest, HttpServletResponse)' in 'io. grpc. servlet. GrpcServlet'; overridden method is final

Yes my changes does not match grpc library but it's very useful for application server users and finally it's easy realize in library)

@panchenko
Copy link
Contributor

@long76 you can copy GrpcServlet into your code base, that's a small class )

@long76
Copy link
Author

long76 commented Jan 17, 2025

@long76 you can copy GrpcServlet into your code base, that's a small class )

Copy paste 😒 i better use our release with patch)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants