rempei
@rempei

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

CORSの問題が解決しない

解決したいこと

JavaScriptでAPIを呼び出す関数を作成し、
Javaのコントローラで適当に作ったデータベースのデータを取得しレスポンスとして返すということをやりたいのですが、
CORSがブラウザでレスポンスをブロックしましたというエラーが出ます。
このエラーの解決法が分かる方がいらっしゃいましたらお助け下さい。
JavaはPlayフレームワークを使用しており諸事情でver1.4.3です。

発生している問題・エラー

Access to XMLHttpRequest at 'http://localhost:9000/api/vital' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Vital.js:35 APIリクエストエラー: AxiosError {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {…}, request: XMLHttpRequest, …}code: "ERR_NETWORK"config: {transitional: {…}, adapter: Array(2), transformRequest: Array(1), transformResponse: Array(1), timeout: 0, …}message: "Network Error"name: "AxiosError"request: XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}stack: "AxiosError: Network Error\n    at XMLHttpRequest.handleError (http://localhost:3000/static/js/bundle.js:111889:14)\n    at Axios.request (http://localhost:3000/static/js/bundle.js:112341:41)\n    at async callApi (http://localhost:3000/static/js/bundle.js:1441:22)\n    at async fetchData (http://localhost:3000/static/js/bundle.js:973:20)"[[Prototype]]: Error
fetchData @ Vital.js:35
await in fetchData(非同期)
(匿名) @ Vital.js:23
commitHookEffectListMount @ react-dom.development.js:23150
invokePassiveEffectMountInDEV @ react-dom.development.js:25154
invokeEffectsInDev @ react-dom.development.js:27351
commitDoubleInvokeEffectsInDEV @ react-dom.development.js:27330
flushPassiveEffectsImpl @ react-dom.development.js:27056
flushPassiveEffects @ react-dom.development.js:26984
(匿名) @ react-dom.development.js:26769
workLoop @ scheduler.development.js:266
flushWork @ scheduler.development.js:239
performWorkUntilDeadline @ scheduler.development.js:533
他 10 件のフレームを表示
一部表示
callApi.js:19 
        
        
       GET http://localhost:9000/api/vital net::ERR_FAILED 200 (OK)

フロントエンド側

useEffect(() => {
    console.log("これからデータを取得します")
    fetchData()
  }, [])

  async function fetchData() {
    try {
      const data = await callApi({
        method: 'GET',
        path: '/api/vital',
      });
      console.log("data: " + data)
    } catch (error) {
      console.error('APIリクエストエラー:', error);
    }
  }
const API_URL = "http://localhost:9000";

  async function callApi({ method, path, body, params, query, headers = {} }) {
    try {
      const url = `${API_URL}${path}`  // path=/api/vital
      const options = {
        method: method.toUpperCase(),
        url,
        params,
        data: body,
        headers: {
          'Content-Type': 'application/json',
          ...headers
        }
      };

      const response = await axios(options);

      return response.data;
    } catch (error) {
      throw error;
    }
  }

  export default callApi;

### バックエンド側

@RestController
public class ApiController extends Controller {
  
  public List<Riyousya> vital() {
    List<Riyousya> riyousyas = Riyousya.findAll();
      for(Riyousya riyousya : riyousyas) {
          System.out.println(riyousya.name);
      }

    return riyousyas;
  }
}
@Entity
@Table(name = "riyousya")
public class Riyousya extends Model {
  
  @Id
  public Long id;
  public String name;

  public Riyousya(String name) {
    this.name = name;
  }
}

public class CorsFilter extends Controller {

    @Before
    public static void setCORS() {
        response.accessControl("*");
    }


    public static void filter() {
        if (request.method.equals("OPTIONS")) {
            response.headers.put("Access-Control-Allow-Origin", new Header("Access-Control-Allow-Origin", "http://localhost:3000/vital"));
            response.headers.put("Access-Control-Allow-Methods", new Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"));
            response.headers.put("Access-Control-Allow-Headers", new Header("Access-Control-Allow-Headers", "Content-Type, Authorization"));
            response.headers.put("Access-Control-Max-Age", new Header("Access-Control-Max-Age", "3600"));
            response.status = StatusCode.OK;
            return;
        }
        response.headers.put("Access-Control-Allow-Origin", new Header("Access-Control-Allow-Origin", "*"));
        ActionInvoker.invoke(request, response);
    }


}

ルーティング設定

GET      /api/vital            ApiController.vital
*       /api/vital              CorsFilter    

自分で試したこと

System.out.println(riyousya.name);
の内容はターミナルに正しく表示されているのですが
フロントエンド側のコンソールを開くとエラーになっています。

0

1Answer

JavaScriptでAPIを呼び出す関数を作成し、Javaのコントローラで適当に作ったデータベースのデータを取得しレスポンスとして返す

その API は Web サーバーでホストされていると思いますが、その Web サーバーで CORS 対応するほかありません。Play とか触ったこともないので具体的な設定方法は分かりませんが、「play cors」でググるとフィルターを使うなどの記事がヒットします。調べてみてはいかが?

ちなみに、要求側はブラウザの仕事で開発者は何もする必要はありません。

1Like

Comments

  1. @rempei

    Questioner

    ご回答ありがとうございます。

    そちらの記事のフィルターはplayのver2.xでないと使えないらしく、
    私のplayはver1.4.3です。こちらのバージョンで動かさないといけないので使えませんでした。

    私のコードを見ておかしなところに心当たりがあれば教えてほしいです。

  2. @rempei

    Questioner

    過去のスレッドは途中で他のエラーに気づいてそちらを治していたのと、
    バージョンが違うのでその方法は使えないと知っていたので、これ以上playの経験のない方に追及しても面倒がられるだろうと思い別記事にて質問していました。

    有識者に質問できないときのアドバイスなどあれば教えてほしいです。

Your answer might help someone💌