crisefd

crisefd

Hi. I’m building a rest API using Phoenix and a UI using VueJS. I have a signup endpoint in the API that returns 400 error code when requesting using my UI, but it returns 201 when using querying from postman.

This works:

curl 'http://localhost:4000/v1/users/signup' -H 'Content-Type: application/json'   --data-binary '{"user":{"email":"dummy@example.com","username":"dummy@example.com","password":"password123456"}}' 

And it fails when the UI issues the requests:

But for some reason when I check the browser devtools I see that the content-type is set to application/json for both response headers and request headers. And I don’t know how, my JS logic explicitly sets the header to ‘content-type’: ‘application/json’

Showing Posts 1 to 8

kokolegorille

kokolegorille

Hello, it’s hard to answer without code…

I am not familiar with Vue, but I don’t think it does the request by itself.

Something like fetch, or axios?

It would be nice to see how your client js code does the request to your API.

crisefd

crisefd OP

It’s a plain JS function really. All it does is call the fetch API and return the response as an observable:

export function request(method, url, payload) {
  const body = JSON.stringify(payload);
  const parameters = {
    headers: { 'Content-Type': 'application/json' } ,
    method: method,
    mode: "no-cors",
    body: body,
    cache: "default",
  };
  return Observable.create(observer => {
    fetch(url, parameters)
      .then(response => {
        observer.next(response);
        observer.complete();
      })
      .catch(error => {
        observer.error(error);
      });
  });
}

kokolegorille

kokolegorille

Those are my headers with axios…

const auth_headers = () => ({
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${AuthService.loadToken()}`,
  },
  credentials: 'same-origin',
});

My headers are a little bit different because I pass a token, but I can see I also added Accept keyword.

amnu3387

amnu3387

I think if you’re using the browser fetchAPI you need to create the headers from the constructor, I use this:

export function requester({ method, url, data, accept, content_type }, token) {
    let body = typeof data === "string" ? data : JSON.stringify(data);

    token = token ? token : "";
    content_type = content_type ? content_type : "application/json";
    accept = accept ? accept : "application/json";
    
    if (process && process.server) {
        const fetch = require("node-fetch");
        let headers = {
            "Bearer": token,
            "Content-Type": content_type,
            "Accept": accept
        };
        let request = {
            method: method,
            headers: headers,
            body: body,
            mode: "cors"
        };

        return fetch(url, request)
            .then(response => response.json())
            .catch(error => { return {error: error.message} });
        
    } else {
        
        let headers = new Headers({
            "Bearer": token,
            "Content-Type": content_type,
            "Accept": accept
        });
        
        let request = new Request(url, {
            method: method,
            headers: headers,
            body: body,
            mode: "cors"
        });
        
        return fetch(request)
            .then(response => response.json())
            .catch(error => { return {error: error.message} });
    }
}
crisefd

crisefd OP

Found the answer to my problem here. “application/json” is only a valid content type with CORS.

Now my problem is how to configure CORS in my phoenix api. I’m using cors_plug. But is not working, I’m still getting in my request.

Access to fetch at 'http://localhost:4000/v1/users/signup' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

This is my CORS config in router.ex file

defmodule DumyApiWeb.Router do
  use DummyApiWeb, :router
...
pipeline :v1 do
    plug CORSPlug, origin: "http://localhost:8080"
    plug DummyApiWeb.Version, version: :v1
end
...
scope "/v1", DummyApiWeb do
    pipe_through :v1
    post "/users/signup", UserController, :create
    post "/users/signin", UserController, :signin
  end
...
end
crisefd

crisefd OP

Solved: I had to defined an options method for UserController to make it work.

Codball

Codball

Can you elaborate? Maybe with a code example?

Exadra37

Exadra37

I would recommend you to understand the mechanics of pre-flight request, aka the one that is done with OPTIONS, and then followed by the real GET, POST, PUT or DELETE request.

A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood.

It is an OPTIONS request, using three HTTP request headers: Access-Control-Request-Method , Access-Control-Request-Headers , and the Origin header.

A preflight request is automatically issued by a browser, when needed. In normal cases, front-end developers don’t need to craft such requests themselves.

Now that you are familiar with a pre-fligth request you can follow the article How to Configure CORS on your Phoenix Application to learn how to do them.

Almost every developer has faced with CORS trouble, but if you haven’t. CORS is just a http mechanism that uses specific headers to grant permission to other domains get some of your data. So imagine that you have a REST API with the domain www.outsiderhost:4000 and you have your SPA hosted in www.localhost:3000 . As you see they are not the same domain, so you have to grant access permission to www.localhost:3000 to get the data from www.outsiderhost:4000 .

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews