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

Dashboard resources aren't accessible from gateway #30

Closed
chlegou opened this issue Jul 28, 2020 · 18 comments
Closed

Dashboard resources aren't accessible from gateway #30

chlegou opened this issue Jul 28, 2020 · 18 comments
Assignees
Labels
bug Something isn't working

Comments

@chlegou
Copy link

chlegou commented Jul 28, 2020

Hi again :)

I have noticed that the rqueue dashboard isn't accessible from a gateway of a microservice architecture server.

How to Reproduce

i have checked the source code of the dashboard template, and it looks like the href links (css + js files) are static to direct endpoint. See here.
for this, the resource files aren't accessible. please change the href links to accept any entry path.

Additional Details

Here is an example of HTTP calling the dashboard from a direct microservice and from the gateway.

MS: http://localhost:8001/rqueue   
Gateway: http://localhost:8000/services/rqueue-service/rqueue

Please make resources accessible from any dynamic endpoint.

Thanks. :)

@sonus21
Copy link
Owner

sonus21 commented Jul 29, 2020

Will fix this, allow me some time. You can raise a PR as you know where to make this changes. I believe dashboard links are not working and static media can't be downloaded.

@sonus21 sonus21 added the bug Something isn't working label Jul 29, 2020
@sonus21
Copy link
Owner

sonus21 commented Jul 29, 2020

We need to make other changes as well, it's not only base.html, js files needs to be changed as well.

@chlegou
Copy link
Author

chlegou commented Jul 30, 2020

sure, take your time :)

if the problem is related to js + css files only, i recommend loading them from any trusted CDN.

...Just testing something right now, (again, if the problem is related to js + css files only), i was able to reach resource files from the gateway with this direct link (example):

http://localhost:8000/services/rqueue-service/rqueue/vendor/jquery/jquery.min.js

looking again for the base.html file, i believe removing /rqueue/ from all the href and src will make it work.
for example, this line would be:

<script src="vendor/jquery/jquery.min.js"></script>

I have peeked the rqueue.js file also, i believe same changes (removing /rqueue/) would work also.

if this worked, i believe that it could be a quick fix of the problem. Please try it before any other changes ;)

... Thinking about impacts, the only dependency is between the path prefix and the public resources folder named rqueue which could be mapped in a way to be configurable from the properties.yml file. Mapping the dynamic path prefix property to the folder will make the library having a dynamic path prefix.

@sonus21
Copy link
Owner

sonus21 commented Jul 31, 2020

Thanks for the information,

looking again for the base.html file, i believe removing /rqueue/ from all the href and src will make it work.
for example, this line would be:

I'm hesitate to ask, why do you think deleting /rqueue would work? /rqueue/<xyz.css/js/*> files are directly linked to public/rqueue resource directory. If we delete then it will have problem finding css/js/image files.

I have peeked the rqueue.js file also, i believe same changes (removing /rqueue/) would work also.

Don't we have to map API urls?

Also, please let me know how did you setup this entire flow, I can try, I was checking Eureka but that does not good fit, which api gateway being used here?

@chlegou
Copy link
Author

chlegou commented Jul 31, 2020

There's a difference between them, relative and absolute paths. Quoting from Here:

Is one a relative path and one an absolute path? ==> Yes.
If your browser is currently pointing at http://foo/bar/baz.html then:
<a href="reset/index.html"> would link to http://foo/bar/reset/index.html.
<a href="/reset/index.html"> would link to http://foo/reset/index.html.

Also from Mozilla Docs :: Linking to relative URLs:

<a href="//example.com">Scheme-relative URL</a> // refer to a url, so the browser will automatically map HTTP and HTTPS protocol
<a href="/en-US/docs/Web/HTML">Origin-relative URL</a> // refers to the website origin (which is currently used)
<a href="./p">Directory-relative URL</a> // refers to the current directory

When looking to the links, i have noticed that you map to /rqueue/..... Also, i previously peeked your controllers, Here and Here
i knew that you have fixed the base path to /rqueue/..... so every link you use in your lib must be /rqueue/....

In case of gateway, the microservice is not running as Origin-relative URL, so for this, we will use the relative path theory to access to views controllers, and let the browser complete the URL mapping. when providing the rest of URL, the browser will append the href link provided to the current relative path


I'm hesitate to ask, why do you think deleting /rqueue would work? /rqueue/<xyz.css/js/*> files are directly linked to public/rqueue resource directory. If we delete then it will have problem finding css/js/image files.

the browser will handle the rest by appending to the relative path, and the controller will return them successfully

Don't we have to map API urls?

We don't have to, in theory, the browser will do that.

Also, please let me know how did you setup this entire flow, I can try, I was checking Eureka but that does not good fit, which api gateway being used here?

I have tried Eureka and consul, they didn't worked really well in production, so i changed to a zuul-proxy gateway. you could generate one quickly using jHipster: https://start.jhipster.tech/generate-application
here is a quicker gateway config: https://ibb.co/J5zPz2B
for the MS running in port 8001, use the one i provided before in last ticket (or any MS you test with..)

then, add in application.yml of gateway:

zuul:
  routes:
    rqueue-service:
      url: http://localhost:8001

@sonus21
Copy link
Owner

sonus21 commented Jul 31, 2020

looking again for the base.html file, i believe removing /rqueue/ from all the href and src will make it work.
for example, this line would be:

Just tried, it's not working for home page.
image

Screenshot 2020-07-31 at 11 09 14 AM

Maybe we should just remove / not /rqueue.

@sonus21
Copy link
Owner

sonus21 commented Jul 31, 2020

Do you think, is it possible for you to setup url prefix in the rqueue app via spring configuration file?
You would just need to do

rqueue.web.url.prefix=/rqueue-service/
Yaml

rqueue:
 web:
   url:
     prefix: /rqueue-service/

This works fine, if I make changes in the code.

@chlegou
Copy link
Author

chlegou commented Aug 1, 2020

Have you looked into network? To see the url that the browser used? And yes, try removing the / only to see if it works.

For rqueue.web.url.prefix, we will let it as alternative. in theory, this could be done by just having the right url pattern and setup.

@sonus21
Copy link
Owner

sonus21 commented Aug 1, 2020

No, it's not working.

It's not working on home page since when we are on http://localhost:8080/rqueue, we refer static files on this page than it's using http://localhost:8080/vendor/js/.... and that's correct as per relative path theory.

Now if you are on another page http://localhost:8080/rqueue/pending, static files now will refer to http://localhost:8080/rqueue/vendor/js/....

As you can see the absolute URL might change as we move from one page to another page, this is creating problem. Another way could be to make dashboard SPA using Angular etc.

sonus21 added a commit that referenced this issue Aug 1, 2020
* Allow consuming dead letter queue messages.
sonus21 added a commit that referenced this issue Aug 1, 2020
…ages (#31)

* * Allow prefixing the urls #30
* Allow consuming dead letter queue messages.

* Fixes for #29

* removed ignored

* updated copyright

* updated versions.
@sonus21
Copy link
Owner

sonus21 commented Aug 1, 2020

Hi Chlegou
Fix is released available at release version 2.0.3-RELEASE.

Thanks.

@chlegou
Copy link
Author

chlegou commented Aug 1, 2020

Ok thanks for the clarification, I will test it out and let you know.

...And yes, thinking of SPA would be a better approach. Also, adding an authentication to it would be a good idea I think...

@sonus21
Copy link
Owner

sonus21 commented Aug 1, 2020

Authentication is not added here, since people might have different types of authentication in the place and they can just place this /rqueue/** in the same group, you can use oauth as well, that could be very simple using Spring security.

Though I'm working on new Rqueue Broker that will have authentication since that would be running as a standalone application. #28

@chlegou
Copy link
Author

chlegou commented Aug 1, 2020

Though I'm working on new Rqueue Broker that will have authentication since that would be running as a standalone application. #28

personally, I would prefer rqueue to be a standalone SPA.

@chlegou
Copy link
Author

chlegou commented Aug 1, 2020

I started testing the version 2.0.3-RELEASE, when running the app, i have seen this error:

2020-08-01 11:53:09.364 ERROR 16252 --- [fication-task-2] .a.i.SimpleAsyncUncaughtExceptionHandler : Unexpected exception occurred invoking async method: public void com.github.sonus21.rqueue.web.service.impl.RqueueSystemManagerServiceImpl.onApplicationEvent(com.github.sonus21.rqueue.models.event.RqueueBootstrapEvent)

java.lang.ClassCastException: class java.lang.String cannot be cast to class com.github.sonus21.rqueue.models.db.QueueConfig (java.lang.String is in module java.base of loader 'bootstrap'; com.github.sonus21.rqueue.models.db.QueueConfig is in unnamed module of loader 'app')
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:176)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at com.github.sonus21.rqueue.web.dao.impl.RqueueSystemConfigDaoImpl.findAllQConfig(RqueueSystemConfigDaoImpl.java:72)
at com.github.sonus21.rqueue.web.dao.impl.RqueueSystemConfigDaoImpl$$FastClassBySpringCGLIB$$719363dc.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
at com.github.sonus21.rqueue.web.dao.impl.RqueueSystemConfigDaoImpl$$EnhancerBySpringCGLIB$$c9b113f6.findAllQConfig(<generated>)
at com.github.sonus21.rqueue.web.service.impl.RqueueSystemManagerServiceImpl.createOrUpdateConfigs(RqueueSystemManagerServiceImpl.java:139)
at com.github.sonus21.rqueue.web.service.impl.RqueueSystemManagerServiceImpl.onApplicationEvent(RqueueSystemManagerServiceImpl.java:167)
at com.github.sonus21.rqueue.web.service.impl.RqueueSystemManagerServiceImpl.onApplicationEvent(RqueueSystemManagerServiceImpl.java:45)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor.lambda$createWrappedRunnable$1(ExceptionHandlingAsyncTaskExecutor.java:78)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)

when running the app with :

rqueue:
  web:
    url:
      prefix: /services/rqueue-service/

From the MS: the rqueue isn't accessible.
From the Gateway: the rqueue dashboard is accessible, but the rest isn't accessible, and returning the same above error with this message (pre-defined error message by jhipster)

{
	type: "https://www.jhipster.tech/problem/problem-with-message",
	title: "Internal Server Error",
	status: 500,
	detail: "class java.lang.String cannot be cast to class com.github.sonus21.rqueue.models.db.QueueConfig (java.lang.String is in module java.base of loader 'bootstrap'; com.github.sonus21.rqueue.models.db.QueueConfig is in unnamed module of loader 'app')",
	path: "/rqueue/queues",
	message: "error.http.500"
}

Is there a way to make it work from both MS and Gateway?

@sonus21
Copy link
Owner

sonus21 commented Aug 1, 2020

{
type: "https://www.jhipster.tech/problem/problem-with-message",
title: "Internal Server Error",
status: 500,
detail: "class java.lang.String cannot be cast to class com.github.sonus21.rqueue.models.db.QueueConfig (java.lang.String is in module java.base of loader 'bootstrap'; com.github.sonus21.rqueue.models.db.QueueConfig is in unnamed module of loader 'app')",
path: "/rqueue/queues",
message: "error.http.500"
}

Thanks for pointing this out, this bug was introduced while fixing #29 :(

Is there a way to make it work from both MS and Gateway?

IMO by just using x-forwarded-prefix header, we can solve the url issue.

@sonus21
Copy link
Owner

sonus21 commented Aug 1, 2020

Sorry, for my last release that's not working.
Can you please try 2.0.4-RC?

Rqueue should be accessible from MS and Gateway as well.

Once you confirm, it's working fine than I'll make a release.

@chlegou
Copy link
Author

chlegou commented Aug 1, 2020

Yes it's working on local! :D even without setting the rqueue.web.url.prefix.
how you fixed it?

@sonus21
Copy link
Owner

sonus21 commented Aug 2, 2020

Thanks for the confirmation, I've released 2.0.4-RELEASE, you can upgrade your code to this version.

x-forwarded-prefix header is the key, we can use this key to identify any prefix.

sonus21 added a commit that referenced this issue Aug 2, 2020
* * Allow prefixing the urls #30
* Allow consuming dead letter queue messages.

* Fixes for #29

* removed ignored

* updated copyright

* updated versions.

* * Fixes for String can not be cast to QueueConfig
* Fixes for messageMetaData being null in TaskAggregator
* Use x-forwarded-prefix to allow the Rqueue to be accessible via  Api Gateway and direct access.

* comment out version.

* Updated code to reflect 2.0.4
@sonus21 sonus21 closed this as completed Aug 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants