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

Support Hash-Routing (again) #24

Open
andys8 opened this issue Nov 26, 2018 · 1 comment
Open

Support Hash-Routing (again) #24

andys8 opened this issue Nov 26, 2018 · 1 comment
Labels

Comments

@andys8
Copy link

andys8 commented Nov 26, 2018

Issue

evancz/url-parser had parseHash. It was removed.

In my case "Url-Routing" is not an option, because the http server is not under my control and will issue 404.

Parsing a url like http://localhost:3000/#/mydata/abe8e05f-e58a-4bfc-81e8-2081c7638407 is hacky. There is fragment. It returns Maybe String. There is no way to parse String with the library. Therefore the workaround shown is working, but not what anybody would want.

Are there alternatives without adding the functionality? If not, can we support hash routing again?

Workaround

parseUrl : Url -> Maybe Route
parseUrl url =
    UrlParser.parse parseRoute (urlFragmentToPath url)

urlFragmentToPath : Url -> Url
urlFragmentToPath url =
    { url | path = Maybe.withDefault "" url.fragment, fragment = Nothing }
@Erudition
Copy link

I have the same problem: I may eventually have a server that can redirect the url path back to elm, but until then, I'd like to use a hash to be able to keep my url stuff (including it's own fragment!) without redirecting to a 404 page.

But from there. I'd like to keep using my normal path parsers like normal!

In that light, you may be interested in the function I wrote for this purpose:

{-| This dense function lets us pretend we have a server redirecting sub-urls (like app/task/57) to our app, even when we don't (like when running as a simple local file). Simply insert a "#" in the address bar, right before the path that gets passed into our app (inc. query&fragment) and this function will make it disappear before our app parses its url.

Example: `http://localhost:8000/www/index.html#/sub/path?hey=there#yo`

is normally parsed as
`url: { fragment = Just "/sub/path?hey=there#yo", host = "localhost", path = "/www/index.html", port_ = Just 8000, protocol = Http, query = Nothing }`

but with this function we can pretend it was:
`url: { fragment = Just "yo", host = "localhost", path = "/www/index.html/sub/path", port_ = Just 8000, protocol = Http, query = Just "hey=there" }`

even though that path may have resulted in a 404 on any host without fancy redirection set up (such as the development environment). Sweet!

-}
bypassFakeFragment : Url.Url -> Url.Url
bypassFakeFragment url =
    case Maybe.map String.uncons url.fragment of
        -- only if "#" is immediately followed by a "/" (path)
        Just (Just ( '/', fakeFragment )) ->
            -- take the url and drop the first "#", then re-parse it
            case String.split "#" (Url.toString url) of
                front :: _ ->
                    -- Url.fromString can fail, but it shouldn't here
                    Maybe.withDefault url <|
                        -- include all the rest (even later "#"s)
                        Url.fromString (front ++ "/" ++ fakeFragment)

                _ ->
                    url

        _ ->
            url

So stick that sucker in right before your Url parser!

Then, when you want to use a URL as it would be with proper server redirection, just stick a hash after the filename. The path that follows will be treated as the path!

@evancz evancz added the request label Feb 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants