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

Make SWAGGER_UI_DOWNLOAD_URL support file:// urls #923

Merged
merged 1 commit into from
May 14, 2024
Merged

Make SWAGGER_UI_DOWNLOAD_URL support file:// urls #923

merged 1 commit into from
May 14, 2024

Conversation

oscar6echo
Copy link
Contributor

@oscar6echo oscar6echo commented May 14, 2024

Cf. merged PR #845 for context.

Resolves #922

@juhaku juhaku merged commit 272ceb8 into juhaku:master May 14, 2024
7 checks passed
} else if url.starts_with("file://") {
let file_path = url.replace("file://", "");
println!("start copy to : {:?}", zip_path);
fs::copy(file_path, zip_path.clone()).unwrap();
Copy link

Choose a reason for hiding this comment

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

No need to copy the file here, right? Wouldn't it be enough to set zip_path = file_path;?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In principle yes, but I prefer having minimal changes between the 2 cases. Here once the download/copy operation is performed, the next steps are exactly the same: Everthing happens in target_dir.

Copy link

Choose a reason for hiding this comment

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

Fwiw, this also means that if the zip file changes then that won't take effect before you cargo clean (or remove the cached file manually).

Copy link
Owner

Choose a reason for hiding this comment

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

Hm. I would then guess it would be useful to make the file type of SWAGGER_UI_DOWNLOAD_URL to just rely on external Swagger UI. Then it is not tied to the cargo lifecycle and can be externally updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that if the file name changes (via env var update), then no need to cargo clean. And these .zip files are meant to be immutable, straight from official source.

Copy link
Owner

Choose a reason for hiding this comment

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

Oh, yeah indeed because of this: println!("cargo:rerun-if-changed={:?}", zip_path.clone());

Copy link
Contributor Author

Choose a reason for hiding this comment

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

and just if !zip_path.exists() {...} tests if download/copy is necessary.

Copy link

Choose a reason for hiding this comment

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

The rerun-if-changed detects if the cached zip changes, not the source zip fwiw.

Copy link
Contributor Author

@oscar6echo oscar6echo May 14, 2024

Choose a reason for hiding this comment

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

So to summarize:

  • one can change a swagger-xxx.zip file via env var SWAGGER_UI_DOWNLOAD_URL with file://
  • these files, typically from official releases, are uniquely identified by their name.
  • if for some reason somebody creates their own, they just have to change filename, change SWAGGER_UI_DOWNLOAD_URL correspondingly and cargo build - if they use the same name it will not be downloaded/copied again.
  • to modifiy the unzipped contents one can use env var SWAGGER_UI_OVERWRITE_FOLDER for selective overwrites - this will be applied in all cases.

This fine grained config allows most if not all custom needs, I think.

println!("start download to : {:?}", zip_path);
download_file(&url, zip_path.clone()).unwrap();
} else if url.starts_with("file://") {
let file_path = url.replace("file://", "");
Copy link

Choose a reason for hiding this comment

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

Arguably, file URLs should still be parsed as URLs. If it looks like a URL I'd usually assume urlencoding and such to apply as usual (on the other hand, building the path becomes easier when you just have to prepend file://... sigh).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Except for space in a path, any other case where prepending file:// is different from parsing as url ?

Copy link

Choose a reason for hiding this comment

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

Lots of special characters end up percentage-encoded. The most obvious case would be that % is used as the escape character, so it itself needs to be escaped as %25.

Copy link
Owner

Choose a reason for hiding this comment

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

Good point, though, not sure whether this actually comes to a problem, but if it does, I guess this could then be addressed. While I did not find a way to simply url encode string for the purpose with a quick look I assume as the ZipArchive works with rust File which itself uses Path to describe the location of a file system agnostic manner it should just simply fail if for one reason or another the rust cannot interpret the input as a valid OsStr that points to a real location.

That said e.g. Unix BASH does require strings to be double quoted to prevent the word globbing thus the variable could just be defined as SWAGGER_UI_DOWNLOAD_URL="/path/to/my spaced swagger ui.zip" if I am not mistaken.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Even if it will seldom be a problem this could be fixed, probably with something like:

// let file_path = url.replace("file://", "");
let file_path = Url.parse(url).to_file_path().unwrap();

What u think ?

Copy link
Owner

Choose a reason for hiding this comment

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

Seems okay, I checked the amount of dependencies and it only has few of them so think we can have this there as well. I believe it does not increase the compile time enormously to out weight the benefit of "validating" URL.

Copy link

@nightkr nightkr May 14, 2024

Choose a reason for hiding this comment

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

reqwest::Url is already just a reexport of url::Url. There's also no reparsing required for reqwest::get, since that also takes a preparsed Url (via IntoUrl).

Copy link
Contributor Author

@oscar6echo oscar6echo May 14, 2024

Choose a reason for hiding this comment

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

Indeed reqwest can be used.
So I committed to my fork:

use reqwest::Url;
// in copy section
let file_path = Url::parse(&url).unwrap().to_file_path().unwrap();

Hopefully that should solve this edge case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since the current PR is merged already, I created a new one with just this improvement: #925

Copy link
Owner

Choose a reason for hiding this comment

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

Merged that one as well

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

Successfully merging this pull request may close these issues.

This PR also breaks sandboxed builds that deny network access, sadly.
3 participants