wking-io / elm-live

⚡ A flexible dev server for Elm. Live reload included.
https://elm-live.com
MIT License
1.05k stars 61 forks source link

Proxying does not work #253

Closed Ploppz closed 3 years ago

Ploppz commented 3 years ago

Proxying does not seem to have any effect in my project. The following files make a fully reproducible example. I have an API running on localhost:8443 and want to send request over there by specifying only the path part of the URL.

elm.json

{
    "type": "application",
    "source-directories": [
        "src"
    ],
    "elm-version": "0.19.1",
    "dependencies": {
        "direct": {
            "elm/browser": "1.0.2",
            "elm/core": "1.0.5",
            "elm/html": "1.0.0",
            "elm/http": "2.0.0",
            "elm/json": "1.1.3"
        },
        "indirect": {
            "elm/bytes": "1.0.8",
            "elm/file": "1.0.5",
            "elm/time": "1.0.0",
            "elm/url": "1.0.0",
            "elm/virtual-dom": "1.0.2"
        }
    },
    "test-dependencies": {
        "direct": {},
        "indirect": {}
    }
}

index.html:

<html>
<head>
  <meta charset="UTF-8">
  <title>Main</title>
  <script src="elm.js"></script>
</head>

<body>
  <div id="myapp"></div>
  <script>
  var app = Elm.Main.init({
    node: document.getElementById('myapp')
  });
  </script>
</body>
</html>

Main.elm:

module Main exposing (..)

import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)
import Http exposing (Error)
import Json.Decode as Decode exposing (Decoder, at, bool, float, int, map2, maybe, string)
import Task exposing (Task)

-- MAIN

main =
    Browser.element
        { init = init
        , update = update
        , subscriptions = subscriptions
        , view = view
        }

init : () -> ( (), Cmd Msg )
init _ =
    ( ()
    , Task.attempt
        (\result -> ())
        (getTask "measurements" string)
    )

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    ( model, Cmd.none )

view : Model -> Html Msg
view model =
    Html.div [] [ Html.text "Hey" ]

subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.none

type alias Msg =
    ()

type alias Model =
    ()

-- Utils

api =
    "/api/v1/"

getTask : String -> Decoder a -> Task Error a
getTask service decoder =
    Http.task
        { method = "get"
        , headers = []
        , url = api ++ service
        , body = Http.emptyBody
        , resolver = Http.stringResolver <| handleJsonResponse decoder
        , timeout = Nothing
        }

handleJsonResponse : Decoder a -> Http.Response String -> Result Error a
handleJsonResponse decoder response =
    case response of
        Http.BadUrl_ url ->
            Err (Http.BadUrl url)

        Http.Timeout_ ->
            Err Http.Timeout

        Http.BadStatus_ { statusCode } _ ->
            Err (Http.BadStatus statusCode)

        Http.NetworkError_ ->
            Err Http.NetworkError

        Http.GoodStatus_ _ body ->
            case Decode.decodeString decoder body of
                Err _ ->
                    Err (Http.BadBody body)

                Ok result ->
                    Ok result

Then I run:

$ elm-live src/Main.elm --proxy-prefix '/api' --proxy-host 'http://localhost:8443' --  --output elm.js

Problem is that in Firefox debugging window under Network tab I can see that it actually sends a request to http://localhost:8000/api/v1/measurements.

julianpistorius commented 3 years ago

This is correct. The browser makes a request to http://localhost:8000/api/v1/measurements, served by elm-live. Then under the hood the elm-live server will proxy the request to http://localhost:8443/api/v1/measurements.

Ploppz commented 3 years ago

Ah, I understand.

But I still have a problem: The requests it sends return 404.

For example I see in the Network tab GET http://localhost:8000/api/v1/measurements that resulted in 404. But if I run curl http://localhost:8443/api/v1/measurements, it is successful.

malaire commented 3 years ago

It looks like proxy prefix is deleted from URL: https://github.com/wking-io/elm-live/blob/master/lib/src/start.js#L187

i.e. http://localhost:8000/api/v1/measurements would be proxied to http://localhost:8443/v1/measurements with --proxy-prefix '/api'

Ploppz commented 3 years ago

Huh, that makes little sense. Thanks for figuring that out.

Now I'm unsure how I can achieve what I want: I want to locally run the app with elm-live and proxy all requests to an API running on a different port. In production, I want the same Elm code to send a request to the path part of URL: /api/v1/, so if it's running on example.com and sends a request to /api/v1/something, it gets sent to example.com/api/v1/something

julianpistorius commented 3 years ago

@Ploppz Add /api to the proxy-host as well, like so:

elm-live src/Main.elm --proxy-prefix '/api' --proxy-host 'http://localhost:8443/api' --  --output elm.js

See https://www.elm-live.com/#getting-started and scroll down to documentation for --proxy-prefix:

NOTE: The string passed to --proxy-prefix will be removed from the --proxy-host url. If you would like the url to include the prefix just add it there as well like: http://localhost:5000/api

Ploppz commented 3 years ago

Ahh missed that, sorry

julianpistorius commented 3 years ago

No problem! Glad to hear you're up & running. 👋