Handle different URL patterns in Zuul filters - spring-boot

I have two types of URL patterns as below.
/gateway/secure/api/user/getUser
/gateway/nonsecure/api/user/getUser
(Context root of zuul gateway application is gateway)
Using zuul filters I'm trying to implement two different logics based on secure and nonsecure URL patterns. I've written a pre-filter and seems it's not even executing that filter for above URL patterns. I could see gateway is throwing 404. When I try to access microservice without secure or nonsecure its working as expected. Below are the property changes I've done so far.
Context root of downstream microservice is api/user
zuul.prefix=/secure
zuul.routes.user.path=/api/user/**
zuul.routes.user.service-id=user
zuul.prefix=/nonsecure
zuul.routes.user.path=/api/user/**
zuul.routes.user.service-id=user
I've already tried by giving zuul.prefix and it seems prefix is setting as globally and cant apply only for specific routes. How can I achieve this? Can anyone please advice.Thanks

As you noted, the zuul.prefix property affects all mappings and can only be defined once. So, drop the zuul.prefix property and add the corresponding prefix to each zuul.routes.*.path properties:
zuul.routes.user.path=/secure/api/user/**
zuul.routes.user.service-id=user
zuul.routes.user.path=/nonsecure/api/user/**
zuul.routes.user.service-id=user
Note that, according to the documentation:
zuul.stripPrefix only applies to the prefix set in zuul.prefix. It does not have any effect on prefixes defined within a given route’s path.

Related

Spring Cloud Gateway: why route uri property ignored?

I have only this route conf
spring.cloud.gateway.routes[0].id=x-service
spring.cloud.gateway.routes[0].uri=http://localhost:5555/x-service/v1/private/files
spring.cloud.gateway.routes[0].predicates[0]=Path=/v1/private/files
but app redirects to /v1/private/files.
How to fix this?
AFAIK spring-cloud-gateway Route builder takes into account only hostname and port passed to UriSpec.uri(String uri), so only http://localhost:5555 matters at this point.
So you need to rewrite your path, using RewritePath gateway filter, like this:
spring.cloud.gateway.routes[0].filters[0]=RewritePath=/v1/private/files, /x-service/v1/private/files
First argument is the original path, second - a replacer.
RegEx also can be used there.
Take a look at spring-cloud-gateway reference docs for details.
Also I suggest reading this article.

AWS APIGW - Access static HTTP Headers for Integration Request in Mapping Template for Lambda

I am trying to modify an API GW config similar to what is found here https://oozio.medium.com/serverless-discord-bot-55f95f26f743
What I need to do is pass to lambda a custom static HTTP Header. I have defined in APIGW -> /{resource} -> Integration Request -> HTTP Headers: a header like {"Name": "application", "Mapped from": "'discord'", "Caching": false} (with single ticks as noted in the documentation for a static value)
This header never appears in the list of headers from the mapping template. I've spent the better part of a day trying to solve this.
Simplified question:
How do you access a static HTTP Header defined in Integration Request, in the Mapping Template?
TIA
After working with AWS support, this is apparently not possible.
Many Thanks for your kind patience. After our call I started to look for a possible
solution to fetch the statically set HTTP header in the mapping template, but
unfortunately could not find any solution.
I then discussed this scenario with my colleagues and also reached out to the
back-end API Gateway Service Team. It seems that this is something that is not
possible currently.
We cannot access the static header value defined in the integration request, in
the request body mapping template. If your use case needs to send the static header
in body for non proxy integration then it is recommended that you may define it
statically in the body mapping template directly.
I understand as you explained to me how you need to access the header in the mapping
template but unfortunately this does not seem to have a solution. Although the
statically set header is seen to be passed in the API Gateway logs, there is no
mechanism in the lambda service to fetch these headers.
Currently, I can ask the Service Team to consider the same as a feature request but
I wont be having a ETA available and also would need a solid reasoning since the
same can be done in the mapping template.
The workaround at this time (March 2021) has to be expressing it directly in the mapping template itself, or using Proxy for Lambda.
The following was provided as justification for the feature request.
When creating APIGW via a templating process (Such as terraform), being able to
express 'API Wide' variables is a useful tool for sending contextual information
to a backend integration. For example, a Lambda that can process requests from
multiple sources, but it needs to know which source should be used. While the
value can be statically expressed in the mapping template, having it be a
variable as part of the API allows for better visibility and management as its
an interact-able component, where as the mapping template is effectively a
complex string. This also does not need to be a header, it could simply be
"integration variables" that allow you to define simple k:v pairs that are either
passed as part of context, or accessible in $context within the mapping template.
While statically expressing it in the mapping template is a workaround, it is
only that.

How to poll the quality gate execution status?

I would like to poll the quality gate execution status of my SonarQube 6.3 instance using a REST api call. I went through a few api calls, which did not give me the expected results.
I tried to use these urls:
http://localhost:9000/api/resources
http://localhost:9000/api/components
But I always got this response:
{"errors":[{"msg":"Unknown url : /api/resources"}]}
How can I poll the quality gate execution status via REST?
http://localhost:9000/web_api lists the web service endpoints available on your server and provides documentation for each one. In my copy of 6.3, the documentation for "api/resources" says
Removed since 6.3, please use api/components and api/measures instead
You say you've tried http://localhost:9000/api/components and gotten an error. That's because there's not actually a web service there. You'll have to add the qualifier for the service you want, such as /api/components/search, as described in the docs for that set of services: http://localhost:9000/web_api/api/components
In fact there are 5 parts in a correct SonarQube web api url. They can be seen like that domain/api/controller/action?parameters, for example http://localhost:9000/api/components/show?componentKey=blue.
So we have:
domain: which is represented by http://localhost:9000 in the example, it is the address where you can call your SonarQube server
api: which is represented by /api in the example, it is the base path of all web service in SonarQube
controller: which is represented by /components in the example, it represents a pool of web service concerning a given theme (issues, profiles, components, etc.)
action: which is represented by /show in the example, it is a unit action that you can perform through the web service, for example: show, search, list, backup, delete, etc.
parameters: which is represented by ?componentKey=bluein the example, they are not always mandatory but often allow you to specify further information to get more precise results
What you have forgotten here is at means to specify an action.
http://localhost:9000/api/project_analyses/search?project=myProjectname&category=QUALITY_GATE
This query returned the status of my quality gate. Here I have mentioned the project name as myProjectname

REST Web API URL to update a resource property

To update the resource i have exposed following reset web api url -
http://server.com/api/v1/{companyid}/resources/{resourceid}
and request body contains the resource to be updated.
I have also exposed a seperate API to update a property of same resource. From business rule perspective this is special property and cannot be updated/retrieved along with normal resource api.
So using following url to expose separate api as below -
http://server.com/api/v1/{companyid}/resources/{resourceid}/property?propertyKey=propertyValue
this does not sound good. Is there better approach?
Answer from the comments for others
PUT api/v1/{companyid}/resources/{resourceid}/{property} with the Body containing the value of the property is one way.
PUT api/v1/{companyid}/resources/{resourceid}/{property}/{propertyvalue} is another way if you want the value entirely in the URL.
Of course, http://server.com/api/v1/{companyid}/resources/{resourceid}/property?propertyKey=propertyValue is also probably fine.
As #David-Brabant mentioned don't version your API's in the URL

Easy way for no-content without controller

I am using Spring Security with Spring Controllers. There are some weird requests caused by some third party browser extension ending such as undefined or weird hexadecimal numbers. I would like to configure my application to block these requests but I could not find an easy way.
I do not want to declare a empty controller for this purpose. What is the correct way to return no-content for these requests?
Edit:
Some sample requets:
/activity/favorites/undefined
/activity/favorites/my/undefined
/help/undefined
Create some servlet filter that is invoked for every request (*). That filter has to check the request URL, and if it is on of the "strangers" that return what you want, but prevent the request from being future processed.

Resources