programing

골랑에서 CORS를 유효하게 하다

coolbiz 2023. 3. 15. 23:21
반응형

골랑에서 CORS를 유효하게 하다

안녕하세요, 저는 rest apis를 구현하고 있으며, 이를 위해 크로스 오리진 요청을 처리하고 싶습니다.

현재 진행 중인 작업:

AWS의 Go-server 코드:

func (c *UserController) Login(w http.ResponseWriter, r *http.Request, ctx *rack.Context) {
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
...
...
c.render.Json(w,rsp, http.StatusOK)
return
}

localhost의 Ajax 코드:

<script>
$( document ).ready(function() {
    console.log( "ready!" );
    $.ajax({
        url: 'http://ip:8080/login',
        crossDomain: true, //set as a cross domain requests
        withCredentials:false,
        type: 'post',
        success: function (data) {
            alert("Data " + data);
        },
    });
});

브라우저 콘솔에서 XMLHttpRequest cannot load http://ip:8080/login 오류가 발생합니다. 요청된 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다. 따라서 오리진 'http://localhost:8081'은 액세스가 허용되지 않습니다. 응답의 상태 코드는 HTTP 422였습니다.

비행 전 옵션을 추가하려고 했습니다.

func corsRoute(app *app.App) {
allowedHeaders := "Accept, Content-Type, Content-Length, Accept-Encoding, Authorization,X-CSRF-Token"

f := func(w http.ResponseWriter, r *http.Request) {
    if origin := r.Header.Get("Origin"); origin != "" {
        w.Header().Set("Access-Control-Allow-Origin", "*")
        w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
        w.Header().Set("Access-Control-Allow-Headers", allowedHeaders)
        w.Header().Set("Access-Control-Expose-Headers", "Authorization")
    }
    return
}
app.Router.Options("/*p", f, publicRouteConstraint)
}

하지만 그것은 효과가 없다.

어떻게 하면 고칠 수 있을까?

용 i i i i를 쓴다.gorilla/mux서버를 를 사용할 수 있습니다.Go RESTful API는 JavaScript를 합니다.

는 My Go Server에서 합니다.localhost:9091버버: :

router := mux.NewRouter()
//api route is /people, 
//Methods("GET", "OPTIONS") means it support GET, OPTIONS
router.HandleFunc("/people", GetPeopleAPI).Methods("GET", "OPTIONS")
log.Fatal(http.ListenAndServe(":9091", router))

는 주는 것을 발견한다.OPTIONS중요한 것은 다음과 같습니다.그렇지 않으면 에러가 발생합니다.

OPTIONS http://localhost:9091/people 405(방식은 허용되지 않습니다)

http://localhost:9091/people: 로드에 실패했습니다.비행 전 요청에 대한 응답이 액세스 제어 검사를 통과하지 못했습니다.요청된 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다.따라서 오리진 'http://localhost:9092'는 액세스가 허용되지 않습니다.응답은 HTTP 상태 코드 405였습니다.

한 후에OPTIONS효과가 좋습니다.는 이 기사에서 아이디어를 얻었다.

또한 MDN CORS 문서에는 다음과 같은 내용이 기재되어 있습니다.

또한 서버 데이터에 부작용을 일으킬 수 있는HTTP 요구 방식에서는 브라우저가 요구를 '프리플라이트'하고 HTTP OPTIONS 요구 방식을 사용하여 서버에서 지원되는 방식을 요청한 후 서버에서 '승인'하면 실제 요청을 실제 HTTP 요구 방식으로 전송하도록 규정하고 있습니다.

다음은 api GetPeople 입니다.API 메서드, 코멘트하는 메서드에서 메모 //여기서 CORS 허용 * 또는 특정 출처로 CORS의 개념을 설명하는 또 다른 유사한 답변이 있습니다.

func GetPeopleAPI(w http.ResponseWriter, r *http.Request) {

    //Allow CORS here By * or specific origin
    w.Header().Set("Access-Control-Allow-Origin", "*")

    w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
    // return "OKOK"
    json.NewEncoder(w).Encode("OKOK")
}

javascript를 .localhost:9092는 javascript에서 localhost:9092

function GetPeople() {
    try {
        var xhttp = new XMLHttpRequest();
        xhttp.open("GET", "http://localhost:9091/people", false);
        xhttp.setRequestHeader("Content-type", "text/html");
        xhttp.send();
        var response = JSON.parse(xhttp.response);
        alert(xhttp.response);
    } catch (error) {
        alert(error.message);
    }
}

요구는 할 수 ."OKOK".

응답/ 헤더 는, 「있다」등의 할 수 .Fiddler.

힌트 고마워요. 모두 머리글에 있어요!서버 측에서는 다음 golang 헤더만 사용합니다.

w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Access-Control-Allow-Origin", "*")

다음 JQuery와 연동됩니다.

<script 
src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
<script>
$.ajax({
    type: 'GET',
    url: 'https://www.XXXXXXX.org/QueryUserID?u=juXXXXny&p=blXXXXXne',
    crossDomain: true,
    dataType: 'text',
    success: function(responseData, textStatus, jqXHR) {
        alert(responseData);
            },
    error: function (responseData, textStatus, errorThrown) {
        alert('POST failed.');
    }
});
</script>

https://github.com/rs/cors 에서 확인하실 수 있습니다.

이렇게 하면Options요청도 있습니다.

GO 서버 설정:

package main

import (
  "net/http"
)


  func Cors(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "text/html; charset=ascii")
  w.Header().Set("Access-Control-Allow-Origin", "*")
  w.Header().Set("Access-Control-Allow-Headers","Content-Type,access-control-allow-origin, access-control-allow-headers")
          w.Write([]byte("Hello, World!"))
  }

  func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/plm/cors",Cors)
  http.ListenAndServe(":8081", mux)
}

클라이언트 JQUERY AJAX 설정:

<head>
       <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
       </script>
</head>
<body>

              <br> Please confirm to proceed : <button class="myConfirmButton1">Go!!</button>

             <div id="loader1" style="display:none;">loading...</div>
             <div id="loader2" style="display:none;">...done</div>
             <div id="myFeedback1"></div>

          <script>
          $(document).ready(function(){
            $(".myConfirmButton1").click(function(){
              $('#loader1').show();
              $.ajax({
                url:"http://[webserver.domain.com:8081]/plm/cors",
                dataType:'html',
                headers: {"Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "access-control-allow-origin, access-control-allow-headers"},
                type:'get',
                contentType: 'application/x-www-form-urlencoded',
                success: function( data, textStatus, jQxhr ){
                $('#loader1').hide();
                $('#loader2').show();
                $('#myFeedback1').html( data );
                        },
                error: function( jqXhr, textStatus, errorThrown ){
                $('#loader1').hide();
                $('#myFeedback1').html( errorThrown );
                alert("error" + errorThrown);
                        }
                });
           });
          });
          </script>
</body>

클라이언트 TEST REQUEST가 컬로 되어 응답을 취득했습니다.

curl - iXGET http://[webserver.domain.com:8081]/plm/module

HTTP/1.1 200 OK
Access-Control-Allow-Headers: Content-Type,access-control-allow-origin, access-control-allow-headers
Access-Control-Allow-Origin: *
Content-Type: text/html; charset=ascii
Date: Wed, 17 Jan 2018 13:28:28 GMT
Content-Length: 13

Hello, World!

CORS를 허용하려면 OPTIONS 메서드를 사용하여 실제 쿼리 전에 브라우저가 보내는 모든 Preflight 요청을 동일한 경로에 수신해야 합니다.

첫 번째 방법은 다음과 같이 수동으로 관리하는 것입니다.

func setupCORS(w *http.ResponseWriter, req *http.Request) {
    (*w).Header().Set("Access-Control-Allow-Origin", "*")
    (*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
    (*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}

func indexHandler(w http.ResponseWriter, req *http.Request) {
    setupCORS(&w, req)
    if (*req).Method == "OPTIONS" {
        return
    }

    // process the request...
}

두 번째 방법은 https://github.com/rs/cors과 같은 서드파티제의 pkg에 즉시 사용할 수 있도록 하는 것입니다.

package main

import (
    "net/http"

    "github.com/rs/cors"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        w.Write([]byte("{\"hello\": \"world\"}"))
    })

    // cors.AllowAll() setup the middleware with default options being
    // all origins accepted with simple methods (GET, POST). See
    // documentation below for more options.
    handler := cors.AllowAll().Handler(mux)
    http.ListenAndServe(":8080", handler)
}

모든 훌륭한 답변에 추가: appHandler 패턴을 사용하는 모든 핸들러에 헤더를 설정하는 대신 다음을 수행합니다.

type Handler func(http.ResponseWriter, *http.Request) *Error

func (fn Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
    if e := fn(w, r); e != nil { // e is *appError, not os.Error.
        http.Error(w, e.Message, e.Code)
    }
}

func Login(w http.ResponseWriter, r *http.Request) *Error {
   ...
   return nil
}

r.Handle("/login", Handler(Login))

네, 이 문제로 인해 몇 가지 문제가 발생했지만 사용해야 하는 수정 방법을 찾았습니다.

github.com/gorilla/handlers

Gollila/mux lib와 함께

그래서 여기 작은 조각이 있다.

r := mux.NewRouter()
header := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization"})
methods := handlers.AllowedMethods([]string{"GET", "POST", "PUT", "HEAD", "OPTIONS"})
origins := handlers.AllowedOrigins([]string{"*"})
api := r.PathPrefix("/api").Subrouter()
api.Handle("/route", function).Methods("GET", "OPTIONS")
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    _, _ = fmt.Fprint(w, "hello")
})

err := http.ListenAndServe(":9000", handlers.CORS(header, methods, origins)(r))

if err != nil {
    fmt.Println(err)
}

이것은 너의 문제를 해결할 것이다.

  1. 번째 : cors

    svc.Handle("/", restAPI.Serve(nil))
    
  2. 후 Handle -> Handle Func를 수정합니다.

    svc.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
         setupHeader(rw, req)
         if req.Method == "OPTIONS" {
             rw.WriteHeader(http.StatusOK)
             return
         }
         restAPI.Serve(nil).ServeHTTP(rw, req)
         return
     })
    
    
    
     func setupHeader(rw http.ResponseWriter, req *http.Request) {
            rw.Header().Set("Content-Type", "application/json")
            rw.Header().Set("Access-Control-Allow-Origin", "*")
            rw.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
            rw.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
    }
    

나도 최근에 같은 문제에 직면해 있다. 그리고 나는 단지 그 문제를Access-Control-Allow-Origin제 문제는 해결되지 않았습니다.내가 가지고 있던 문제는 브라우저가 먼저 메시지를 보낸다는 사실이었다.OPTIONS부탁한다

그래서 나는 체크해야만 했다.OPTIONS이 문제를 해결하도록 요청하고 OK 응답을 보냅니다.이렇게 하면 제 크로스 관련 문제의 대부분을 해결할 수 있었습니다.

내가 한 방법의 샘플 코드는 다음과 같다.


이것은 서버측 미들웨어이며, 이 미들웨어는 모든 서버측을 담당합니다.CROS관련 사항

func CORSMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", "*") // change this later
        w.Header().Set("Access-Control-Allow-Credentials", "true")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
        w.Header().Set("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS")

        if r.Method == "OPTIONS" {
            w.WriteHeader(204)
            return
        }

        next.ServeHTTP(w, r)
    })
}

나는 주로 리액트 프레임워크를 사용한다.그리고 아래는 내가 게시물을 만드는 방법의 예시 코드이다.그리고 내가 보통 이것을 앞에서 사용하는 방법이다.

(내 양식도 여기 포믹을 사용합니다)

  <Formik
              initialValues={{ title: "", slug: "" }}
              validate={(values) => {
                const errors = {};
                if (!values.title) {
                  errors.title = "Required";
                } else if (!values.slug) {
                  errors.slug = "Required";
                }
                return errors;
              }}
              onSubmit={(resp, { setSubmitting }) => {
                setTimeout(() => {
                  var encodedPost = btoa(value);
                  resp.post = encodedPost;
                  console.log(JSON.stringify(resp, null, 2));
                  const cookies = new Cookies();
                  let authtoken = cookies.get("auth");

                  /* sending the request */
                  var myHeaders = new Headers();
                  myHeaders.append("Authorization", `Bearer ${authtoken}`);
                  myHeaders.append("Content-Type", "application/json");

                  var requestOptions = {
                    method: "POST",
                    headers: myHeaders,
                    body: JSON.stringify(resp),
                  };

                  fetch(
                    "http://localhost:4000/api/v1/post/create",
                    requestOptions
                  )
                    .then((response) => response.json())
                    .then((result) => {
                      console.log(result);
                      alert(JSON.stringify(result, null, 2));
                    })
                    .catch((error) => {
                      alert(JSON.stringify(error, null, 2));
                    });

                  setSubmitting(false);
                }, 400);
              }}
            >

router := mux.NewRouter()
api := router.PathPrefix("/api/v1").Subrouter()
api.HandleFunc("/getLastDateOfAMonth", lastday.Handler).Methods(http.MethodPost)
c := cors.New(cors.Options{
    AllowedOrigins:   []string{"http://localhost:3000"},
    AllowCredentials: true,
    AllowedMethods:   []string{"GET", "DELETE", "POST", "PUT"},
})
handler := c.Handler(router)
log.Fatal(http.ListenAndServe(":3001", handler))

https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request #:~:text=A%20CORS%20preflight%20request%20is, Headers%20%2C%20및%20the20Origin%20header를 체크해 주세요.

모두 CORS 문제에 직면해 있습니다.-> 수정 -> 백엔드 서버는 CORS를 승인해야 합니다.백엔드 애플리케이션에 Cors를 추가합니다.브라우저로부터의 프리플라이트 요청 시 CORS를 이해할 수 있도록 합니다.

언급URL : https://stackoverflow.com/questions/39507065/enable-cors-in-golang

반응형