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

Limited path rewrites. #2076

Closed
LexManos opened this issue Mar 12, 2024 · 8 comments
Closed

Limited path rewrites. #2076

LexManos opened this issue Mar 12, 2024 · 8 comments
Labels
api Issue addresses the API layer of Reposilite backend enhancement Improvement of existing feature request plugin
Milestone

Comments

@LexManos
Copy link

LexManos commented Mar 12, 2024

Request details

I know I'm late to the party, however looking at upgrading form 2.x to 3.x and saw that path rewriting was removed. As this makes sense from a complexity viewpoint. Is there any possibility of a limited scope of this returning. My main issue is that the maven I run is old and used by tons of people/old software and it's a real hassle/impossible to get them to update anything. However the maven is really simple, it's just one repo with a couple of proxied repos behind it. I don't have to worry about people uploading to re-written addresses because everyone who uploads is easily contactable and can update their paths. I'm concerned with the plethora of existing links out in the internet and in old versions of the software.

So what I am requesting is a single configuration value on GET/HEAD requests.
As a proof of concept I tried this code, and it works exactly how I want it.

--- a/reposilite-backend/src/main/kotlin/com/reposilite/maven/infrastructure/MavenEndpoints.kt
+++ b/reposilite-backend/src/main/kotlin/com/reposilite/maven/infrastructure/MavenEndpoints.kt
@@ -22,6 +22,7 @@ import com.reposilite.maven.api.DeleteRequest
 import com.reposilite.maven.api.DeployRequest
 import com.reposilite.maven.api.LookupRequest
 import com.reposilite.shared.extensions.resultAttachment
+import com.reposilite.storage.api.Location
 import com.reposilite.web.api.ReposiliteRoute
 import io.javalin.community.routing.Route.DELETE
 import io.javalin.community.routing.Route.GET
@@ -60,8 +61,15 @@ internal class MavenEndpoints(
     )
     private val findFile = ReposiliteRoute<Unit>("/{repository}/<gav>", HEAD, GET) {
         accessed {
-            requireGav { gav ->
-                LookupRequest(this?.identifier, requireParameter("repository"), gav)
+            requireGav { gavRaw ->
+                var repo = requireParameter("repository")
+                var gav = gavRaw
+                if (mavenFacade.getRepository(repo) == null) {
+                    gav = Location.of(repo + '/' + gav)
+                    repo = "releases"
+                }
+
+                LookupRequest(this?.identifier, repo, gav)
                     .let { request -> mavenFacade.findFile(request) }
                     .peek {
                         ctx.resultAttachment(

Note: this is just a quick POC as I have no idea how you'd want to store this config value or expose it in the settings menu. But I think it may be simple enough in this limited scope to be worth considering.

Heck, if this is possible in some other way let me know, your update guide says this can be imitated with custom repos, I'm assuming you mean by having a repo for each of the root folders and redirecting it using a loopback url to 'release' repo? Which is a real pain to setup. If there is a simpler option please let me know.

@dzikoysk dzikoysk added question Questions about project and how to use it and removed triage labels Mar 12, 2024
@dzikoysk
Copy link
Owner

Hey, did you consider using a plugin for this? There's a plugin that already does that:

You could also build something similar, probably even as a script in Groovy.

I know I'm late to the party, however looking at upgrading form 2.x to 3.x

Just when I started planning for 4.x 😅

@LexManos
Copy link
Author

LexManos commented Mar 12, 2024

I'm more then happy to use a plugin for this, just trying to figure out one that works. The linked one does not for my use cause because it requires the client to support 30x redirects. Which unfortunately a lot of implementations do not. (yes I know it's a standard that has existed forever, but thus is legacy clients). Currently going down the path of trying to get javlin to be able to reprocess a quest with a modified path. Not having much luck.

Also, is there some plugin repo? I only see the ones listed on your site made by you. Or is it something to just search github for?

@UpcraftLP
Copy link
Contributor

How about running reposilite behind a reverse proxy instead? (nginx, traefik, caddy.. to name a few)

That way you could simply apply some URL rewrite rules at the proxy level and have them be opaque to the connecting client.

@LexManos
Copy link
Author

LexManos commented Mar 12, 2024

That is a possibility, everything is already passing through traefik for one of the servers I manage. But it would be nice to have a simpler/light weight solution for the other servers where a reverse proxy isn't already setup. It's a useful feature of 2.x, that was nuked. Just seems weird to setup a whole other docker/server for what in effect ends up being just editing two strings in the handler.

Plus doing it on Reposilite's end allows for one place integration with adding/removing repositories.
Meaning, to add a Repo using a reverse proxy I would need to add the repo in reposilite, then edit the proxy config to add the repo name to the whitelist of non-rewrites and reboot the proxy.

@dzikoysk
Copy link
Owner

dzikoysk commented Mar 12, 2024

I think that the proper solution should be covered on a plugin api level. I also don't want to make this feature a part of Reposilite's config, because it'd kinda open this whole topic once again.

Probably the easiest way to expose this function could be achieved by moving current endpoint implementation to some sort of a factory, so you'd just simply do something like registerRoute("/*", factory.createMavenEndpoint("releases")).

I'm quite tired right now, so I'll take a look at it a little bit later - hopefully tomorrow.

@dzikoysk dzikoysk added enhancement Improvement of existing feature request api Issue addresses the API layer of Reposilite backend plugin and removed question Questions about project and how to use it labels Mar 12, 2024
@LexManos
Copy link
Author

LexManos commented Mar 13, 2024

Alright, I was able to find a solution that is functional. I'm not the biggest fan of it because it has hardcoded a few magic strings {to filter out frontend files}, and i cant get config to work correct, so if you have any ideas for a better solution let me know.

@dzikoysk
Copy link
Owner

Touching underlying servlet api and frontend specific files might not be the best way to go, I'm not sure if it'd work properly with further request processing 🤔 Instead, I'd try to iterate over root directories in redirected repo and just register a new route for each one of them:

@Plugin(name = "redirect", dependencies = ["local-configuration", "frontend", "maven"])
class RedirectPlugin : ReposilitePlugin() {
private val redirectTo: String? = System.getProperty("reposilite.redirect.default-repository", "")
override fun initialize(): Facade? {
if (redirectTo.isNullOrEmpty()) {
return null
}
val mavenFacade = facade<MavenFacade>()
val mavenEndpoints = MavenEndpoints(
mavenFacade = mavenFacade,
frontendFacade = facade<FrontendFacade>(),
compressionStrategy = facade<LocalConfiguration>().compressionStrategy.get()
)
logger.info("")
logger.info("--- Redirect")
val redirectedRoutes = mavenFacade.getRepository(redirectTo)
?.storageProvider
?.getFiles(Location.of("/"))
?.orNull()
?.map {
logger.info("Redirecting /${it.getSimpleName()}/<gav> to /$redirectTo/${it.getSimpleName()}/<gav>")
ReposiliteRoute<Unit>("/${it.getSimpleName()}/<gav>", HEAD, GET) {
accessed {
mavenEndpoints.findFile(
ctx = ctx,
identifier = this?.identifier,
repository = redirectTo,
gav = it.resolve(requireParameter("gav"))
)
}
}
}
?: emptyList()
event { event: RoutingSetupEvent ->
event.register(redirectedRoutes)
}
return null
}
}

~ #2077

We could hide this behind reposilite.redirect.default-repository property, like we do for some other hidden functionalities, so we don't have to expose this in the public config. Thanks to that, such implementation could be probably just merged to the core sources.

@dzikoysk dzikoysk added this to the 3.5.9 milestone Mar 14, 2024
@dzikoysk
Copy link
Owner

Released with 3.5.9:

I didn't have time to test it tho, so let me know in case of any issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api Issue addresses the API layer of Reposilite backend enhancement Improvement of existing feature request plugin
Projects
None yet
Development

No branches or pull requests

3 participants