Comments (7)
Hi, I've also run into the same issue, but found a workaround.
My setup: Axum server running behind Reverse Proxy, with URL rewrite: "/api" -> "/"
struct PathPrefixAddon;
impl Modify for PathPrefixAddon {
fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
match env::var("PATH_PREFIX") {
Ok(prefix) => openapi.servers = Some(vec![Server::new(prefix)]),
Err(_) => ()
}
}
}
async fn main() {
#[derive(OpenApi)]
#[openapi(modifiers(&PathPrefixAddon))]
struct ApiDoc;
let app = Router::new()
.merge(SwaggerUi::new("/docs").config(Config::new(["openapi.json"])).url("/docs/openapi.json", ApiDoc::openapi()));
}
The PathPrefixAddon
tricks utoipa to use "/{prefix}" to access the server, which essentially adds a prefix to every endpoint.
The .config(Config::new(["openapi.json"]))
is also important so that the Swagger UI would look for the openapi.json with a path relative to the /docs
.
Note that there are other pitfalls to this setup:
- Axum / Utoipa might respond
303
for requests to/docs
to redirect it to Location/docs/
. In your reverse-proxy you also need to setup redirect translation. E.g.: in Nginx I had to addproxy_redirect / /api/;
to prepend the proper prefix.
from utoipa.
The workaround given will not fix the problem with trailing slash redirect from
utoipa/utoipa-swagger-ui/src/axum.rs
Line 52 in 4d798bc
thus if the API is available under prefix
/service
as/api
it will work as/service/api/
but/service/api
will give a bad redirect to/api
Yeah, I've covered that in:
Axum / Utoipa might respond 303 for requests to /docs to redirect it to Location /docs/. In your reverse-proxy you also need to setup redirect translation. E.g.: in Nginx I had to add proxy_redirect / /api/; to prepend the proper prefix.
This is what I have in my nginx reverse proxy to handle that:
server {
location /api {
rewrite /api/(.*) /$1 break;
proxy_pass http://backend-proxied:5000;
proxy_redirect / /api/;
proxy_buffering off;
proxy_set_header Host $host;
}
}
from utoipa.
tricks utoipa to use "/{prefix}" to access the server, which essentially adds a prefix to every endpoint.
Hi @plang-arista, thanks for your workaround. I can confirm it also works for the Swagger UI part when loading openapi.json on Actix-web, the next problem I am facing is the "Try it out" part still using the wrong endpoint.
for example, my server is http://www.abcd.com/, set Apache reverse proxy to http://www.abcd.com/rusttest/ for Rust Actix-web
The swagger UI URL becomes http://www.abcd.com/rusttest/swagger/
The actual API endpoint is http://www.abcd.com/rusttest/api/xxxxABC
The "Try it out" in utoipa swagger UI send request to http://www.abcd.com/api/xxxxABC, the prefix "/rusttest" is missing.
Could you please help to see what's wrong in my code? thanks heaps
use dotenv::dotenv;
use actix_cors::Cors;
use actix_web::{App, HttpServer, web::Data};
use std::{error::Error, env};
use utoipa::{OpenApi, Modify, openapi::server::Server};
use utoipa_swagger_ui::{SwaggerUi, Config};
struct PathPrefixAddon;
impl Modify for PathPrefixAddon {
fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
match env::var("PATH_PREFIX") {
Ok(prefix) => openapi.servers = Some(vec![Server::new(prefix)]),
Err(_) => ()
}
}
}
async fn main() -> Result<(), Box<dyn Error>> {
dotenv().ok();
//Because Apache reverse proxy configuration,
//environment variable need to be set in .env file for PATH_PREFIX
//Auto-generate API documentation using utoipa and utoipa-swagger-ui
#[derive(OpenApi)]
#[openapi(
modifiers(&PathPrefixAddon),
paths(
get_pages,
),
components(schemas(
Page,
))
)]
struct ApiDoc;
let openapi = ApiDoc::openapi();
HttpServer::new(move || {
App::new()
.wrap(Cors::permissive()) // Add this line to enable CORS for all origins
.service(
//Because Apache reverse proxy configuration, we have to use PathPrefixAddon
//It tricks utoipa to use "/{prefix}" to access the server, which essentially adds a prefix to every endpoint.
SwaggerUi::new("/swagger/{_:.*}").config(Config::new(["openapi.json"])).url("/swagger/openapi.json", openapi.clone()),
)
.configure(init_routes) // Route being handled by routes.rs
})
.bind((CONFIG_PARAMETERS.webserver_host.to_string(), CONFIG_PARAMETERS.webserver_port,))?
.run()
.await?;
Ok(())
}
from utoipa.
tricks utoipa to use "/{prefix}" to access the server, which essentially adds a prefix to every endpoint.
Hi @plang-arista, thanks for your workaround. I can confirm it also works for the Swagger UI part when loading openapi.json on Actix-web, the next problem I am facing is the "Try it out" part still using the wrong endpoint.
Hi, this is weird, this should work. Can you add logging that you have set your PATH_PREFIX
env var to /rusttest/
as well? You can also just hard-code that value for your test, to be on the safe side.
In the swagger page you should see a new Drop-Down select, labelled "Servers" with single value /rusttest/
. This is how swagger-ui would know that your /api/xxxxABC
api calls would need to be made against /rusttest/
server on the same host, essentially becoming http://www.abcd.com/rusttest/api/xxxxABC
.
If that variable is also properly set up, I'm not sure how to go on.
from utoipa.
tricks utoipa to use "/{prefix}" to access the server, which essentially adds a prefix to every endpoint.
Hi @plang-arista, thanks for your workaround. I can confirm it also works for the Swagger UI part when loading openapi.json on Actix-web, the next problem I am facing is the "Try it out" part still using the wrong endpoint.
Hi, this is weird, this should work. Can you add logging that you have set your
PATH_PREFIX
env var to/rusttest/
as well? You can also just hard-code that value for your test, to be on the safe side.In the swagger page you should see a new Drop-Down select, labelled "Servers" with single value
/rusttest/
. This is how swagger-ui would know that your/api/xxxxABC
api calls would need to be made against/rusttest/
server on the same host, essentially becominghttp://www.abcd.com/rusttest/api/xxxxABC
.If that variable is also properly set up, I'm not sure how to go on.
Thanks for the reply. For the current swagger page, it didn't show Drop-Down select, labelled "Servers" with single value /rusttest/. So might be env var problem.
As the server is an internal server behind the firewall, so I could not test it over the weekend at home. Will look into this next Monday.
from utoipa.
tricks utoipa to use "/{prefix}" to access the server, which essentially adds a prefix to every endpoint.
Hi @plang-arista, thanks for your workaround. I can confirm it also works for the Swagger UI part when loading openapi.json on Actix-web, the next problem I am facing is the "Try it out" part still using the wrong endpoint.
Hi, this is weird, this should work. Can you add logging that you have set your
PATH_PREFIX
env var to/rusttest/
as well? You can also just hard-code that value for your test, to be on the safe side.In the swagger page you should see a new Drop-Down select, labelled "Servers" with single value
/rusttest/
. This is how swagger-ui would know that your/api/xxxxABC
api calls would need to be made against/rusttest/
server on the same host, essentially becominghttp://www.abcd.com/rusttest/api/xxxxABC
.If that variable is also properly set up, I'm not sure how to go on.
Hi @plang-arista, after I correctly set PATH_PREFIX
env var to /rusttest/
, Swagger UI is working properly now. thanks for your help.
from utoipa.
The workaround given will not fix the problem with trailing slash redirect from
utoipa/utoipa-swagger-ui/src/axum.rs
Line 52 in 4d798bc
thus if the API is available under prefix /service
as /api
it will work as /service/api/
but /service/api
will give a bad redirect to /api
from utoipa.
Related Issues (20)
- GenericType resolution inspecificity HOT 3
- Database HOT 1
- Shouldn't `merge` take Operations into account? HOT 1
- utoipa-gen-4.3.0 leaks crate-private type HOT 2
- Buid dependency with openssl, complicates cross-compilation HOT 1
- Outsource the utoipa::path tuples HOT 1
- Request for Changelog
- Can't leak crate-private type error HOT 3
- Defining Headers in Specific APIs
- Feature Request: IntoResponse add example to ResponseBuilder
- This PR also breaks sandboxed builds that deny network access, sadly.
- Fix compile error for path params, proc macro error migration after effect
- Build script should respect the Cargo `http.cainfo` HOT 1
- utoipa-swagger-ui Release 7.0.2 HOT 4
- Redoc invalid reference token with generics HOT 4
- My Ci is failing HOT 5
- Summary/Description Generation Issue with Multiline First Sentences. HOT 2
- nest(...) attribute doesn't existin last utoipa-gen 4.3.0 crate HOT 1
- Supporting sqlx Json<T>
- utoipa-rapidoc causes panic on axum due to empty path
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from utoipa.