docs works but ui doesn't have routing? - swagger-net

I'm running my api as an application within a site in IIS. The site's url is "http://api.companyName.local/" and the api's url is "http://api.companyName.local/api".
I've got Swagger-Net set up enough that http://api.companyName.local/api/swagger/docs/v1 returns swagger.json and appears to be correct. However no url I can think of brings up the UI. I've tried:
http://api.companyName.local/api/swagger
http://api.companyName.local/api/swagger/
http://api.companyName.local/api/swagger/ui
http://api.companyName.local/api/swagger/ui/
http://api.companyName.local/api/swagger/ui/index
all of which end up with this error:
It looks like the routes are resolving to the StaticFile handler and not the SwaggerUiHandler handler.
This is the setup I'm trying to use
httpConfiguration.EnableSwagger( c => {
c.SingleApiVersion( "v1", "Company Name API" );
c.ResolveConflictingActions( apiDescriptions => apiDescriptions.First( ) );
c.UseFullTypeNameInSchemaIds( );
} ).EnableSwaggerUi( );
I've pulled down the github for Swagger-Net and started to dig around. I see it uses httpConfiguration.VirtualPathRoot in some places so I figure I should mention for my api this resolves to "/" in case that matters.
EDIT:
One interesting thing I just found is that I get different errors from these two urls
http://api.companyName.local/api/swagger/ui/v1
http://api.companyName.local/api/swagger/ui/v2
The one that ends in v1 is getting into the SwaggerUiHandler but the one with v2 errors like it would without v2 at all. So it would seem that something in Swagger-Net is looking at the full url and ignoring it if it doesn't include the version. My api doesn't have versions so this is very annoying.

I finally figured it out! The solution is to add a TransferRequestHandler to the web.config to allow the ui pages to resolve into the api. The reason routes with v1 worked is because my api already had this attribute for routes with v1 in them.
<handlers>
<add name="Swashbuckle-Swagger" verb="*" path="swagger/*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
</handlers>
This snipped was lifted from https://github.com/domaindrivendev/Swashbuckle/issues/57

Related

Backend Returns "Access-Control-Allow-Origin" Header Twice, Each With Different Value

I'm using Python's FastAPI to manage the server's API and Axios hooks on my Frontend.
Here's my code snippet that handles details of the CORS policy on the server:
origins = ["http://localhost:3000"]
*****some code here*****
app = FastAPI(
title=settings.PROJECT_NAME,
version="1.0",
docs_url=f"{settings.API_V1_STR}/docs",
openapi_url=f"{settings.API_V1_STR}/openapi.json",
)
app.container = app
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(api_router, prefix=settings.API_V1_STR)
Here's the relevant hook that I'm using on the Frontend via Axios-hooks axios-hooks docs:
const [
{
response: marketResponse,
loading: marketLoading,
error: marketError,
},
] = useAxios({
url: serverURL("market/list"),
method: "GET",
});
It's important to note that I've double checked the allowed origin.
The issue:
As my web app requests the list via above mentioned axios hoook, the following error appears:
Frontend HTTP Error
Here's the Network Tab's Header Info:
Network's Header Info
As you'll notice Access-Control-Allow-Origin appears there 2x! Once in capped init letter and 2nd time in all lower case. I figured the issue somehow stems from this headers. Unfortunatelly can't find a particular way to fix it.
Thanks for any kind of help!
Googled multiple similiar issues and studied both Axios & Fast Api docs. Unfortunately couldn't find even a slight hint of solution.
The issue
This is actually a known issue with the Starlette CORSMiddleware.
So the issue is that Starlette CORSMiddleware adds the origin header without checking if it already exists. That is by design.
FastAPI is wrapping this module.
If you take a look at the actual Starlette code you will see that it is going to this line.
This explains the upper case version of Access-Control-Allow-Origin.
So why is this happening?
Multiple servers are running. A known issue is if you are using python-socketio then the socketio will add its own version of the header.
I noticed this line:
app.container = app
What is the reason for this? Can you try to comment it out and rerun the code?
Else check if your NGINX is setting CORS.

How can I redirect hundreds of hostnames to other hostnames using nginx

I have a system where many (~20k) subdomains use nginx's default_server, which passes the work off to an app.
I also have many (~100) hostnames that need to be redirected to a correct one, that is different for each hostname and that would then redirect to the default_server.
one.example.com -> eleven.example.com
two.example.com -> twelve.domain.com
three.example.com -> wibble.example.com
blah.domain.com -> fifteen.example.com
The redirects are arbitrary, ie there is no pattern to them.
Rather than having to update nginx config to add a new server block whenever a new redirect is needed or updated I'd prefer to use a map file of some sort that nginx can check for redirects.
Sadly having searched about quite a bit I've not found anything like it, all examples I've found use a new server block for each redirecting host or use regexes. I'd prefer to be able to update a map file or database on the fly that nginx can refer to.
My current best option I have is to update the background app to apply the redirects.
I did previously find the map but it wasn't clear that it could be used in this way and none of the examples showed it. Saying that it turned out to be quite easy.
This is what I have that seems to work;
map $host $redirect_host {
hostnames;
one.david.org eleven.david.org;
two.david.org twelve.steve.org;
three.steve.org thirteen.david.org;
four.steve.org fourteen.steve.org;
}
server {
...
if ($redirect_host) {
return 301 $scheme://$redirect_host$request_uri;
}
...
}
It's a shame that this solution requires nginx restart, but it's not a big deal.

How to set up API gateway without specifying all resources

I have some EC 2 applications (in node.js) that have many REST paths, and since still in development process, the path keep changing.
How can I set up in the api-gateway, that will map to multiple paths, instead of specify each of them?
e.g.
my ec2 end points have:
my.ec2.com/api/test
my.ec2.com/api/test1
my.ec2.com/api/test2
my.ec2.com/api/user/time
my.ec2.com/api/user/time1
my.ec2.com/api/user/time2
instead of setting the all resources in api-gateway,
can I do something like:
api-gateway.amazon.com/api that points to my.ec2.com/api/
and it will resolve any call to http://api-gateway.amazon.com/api/test automatically points to http://my.ec2.com/api/test, etc. ?
As of today, it is still impossible in the API gateway console.
The solution is to use Swagger. then I can use some scripts to generate the Swagger file and import to API gateway. In fact, it is a good solution because I can source control on Swagger.

CakePHP Custom REST Routes

I'm using CakePHP and Backbone.js as a frontend so I want to get CakePHP's REST routing working, but I don't really want to use the default REST routes.
For example, I want to be able to POST to http://example.com/cards/search.json and get a list of results in JSON, however I am getting a 200 status code back, and a blank response which makes me think the routing is not working properly.
I have tested my code using the default REST routes by chagning the search() method of my controller to add(), but I would prefer to be able to properly setup and use custom REST routes.
Router::connect(
"/cards/search",
array(
"[method]" => "POST",
"controller" => "cards",
"action" => "search"
)
);
Router::mapResources('cards');
Router::parseExtensions('json');
The code from my routes.php is above and I'm not entirely sure why it isn't working...either because the documentation on this is a little light, or I just don't understand routing very well.
You can get the json output in this url:
http://localhost:{port}/{api* name in config # app/core}/{controller name}/{things after api_ in function name}/{input parameters}.json
read more in here
You may have to alter the routing to change the name
api
to anything in
Configure::write('Routing.prefixes', array('master', 'api'));
in core.php in app/config
Feel free for a comment and also share your core.php in config for more explanation.

zend soap win7/apache cant remove cache

I did everything, i think:
deleted windows/Temp
soap.wsdl_cache_enabled=0 in php.ini and restarted apache
ini_set("soap.wsdl_cache_enabled", "0"); in handleWDSL, handleSOAP and clientAction!
what else? still getting:
Message: Function ("arrays_work") is not a valid method for this service
That is the new function I added to the service. Also, if I change oldones, nothing happens (for instance, adding functionality to access db).
please...
any clues?
This was solved and in this case was related to other thing: the uri for the wdsl was pointing to an oldone... sorry..