英文:
I want to POST from React to an API created in Golang
问题
我想做什么
我正在为我的 Golang 学习创建一个 Todo 应用程序。
我想用 React 和 Golang 从 POST 请求中读取数据。
代码
Go 后端
package todos
import (
"database/sql"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"time"
"todo-app/auth"
"github.com/joho/godotenv"
)
type Todo struct {
// UserID int `json:"userid"`
Todo string `json:"todo"`
CreatedAt time.Time `json:"createdat"`
UpdatedAt time.Time `json:"updatedat"`
}
type TodoBody struct {
Todo string `json:"todo"`
}
func CreateTodo(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "*")
w.Header().Set("Access-Control-Allow-Origin", "http://localhost:3000")
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Allow-Headers", "*")
e := godotenv.Load()
if e != nil {
log.Fatal(e)
}
dbConnectionInfo := fmt.Sprintf("%s:%s@tcp(127.0.0.1:3306)/go_todo", os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"))
db, err := sql.Open("mysql", dbConnectionInfo)
if err != nil {
log.Fatal(err)
}
defer db.Close()
tokenString := r.Header.Get("Authorization")
tokenString = strings.TrimPrefix(tokenString, "Bearer ")
log.Printf("request token=%s\n", tokenString)
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Fatal(err)
}
log.Printf("request body=%s\n", body)
var data TodoBody
if err := json.Unmarshal(body, &data); err != nil {
log.Println(err)
}
// userId := 12
todo := data.Todo
todoData := Todo{todo, time.Now(), time.Now()}
_, err2 := auth.TokenVerify(tokenString)
if err2 != nil {
log.Fatal(err)
} else {
stmt, err := db.Prepare("INSERT INTO todos (Todo,CreatedAt,UpdatedAt) VALUES(?,?,?)")
if err != nil {
log.Fatal(err)
}
_, err = stmt.Exec(todoData.Todo, todoData.CreatedAt, todoData.UpdatedAt)
if err != nil {
log.Fatal(err)
}
json.NewEncoder(w).Encode(todoData)
}
}
React 前端
import { useState } from "react";
import { useCreateTodo } from "../../hooks/useCreateTodo";
import { BaseButton } from "../atoms/baseButton";
import { TextArea } from "../atoms/textArea";
export const AddTodo = () => {
const [text, setText] = useState("");
const CreateTodo = useCreateTodo();
const token = "Bearer " + sessionStorage.getItem("token");
const onClickCreate = () => {
CreateTodo(token, text);
};
return (
<div>
<TextArea
onChange={(e) => setText(e.target.value)}
defaultValue=""
/>
<BaseButton text="タスクを追加" onClick={onClickCreate} />
</div>
);
};
POST 请求如下
import axios from "axios";
export const useCreateTodo = () => {
const CreateTodo = (token, todo) => {
const URL = "http://127.0.0.1:8080/createtodo";
const data = { todo: todo };
console.log(data);
axios
.post(URL, JSON.stringify(data), { headers: { Authorization: token } })
.then((res) => console.log(res))
.catch((err) => console.log(err));
};
return CreateTodo;
};
如果我在 POST 请求中不添加头部信息,正确的值会传递到 Go 的 ioutil.ReadAll(r.Body)
中,但是如果我添加头部信息,我无法获取到值。
当我使用 Advanced REST client 发送请求到 Go 的 API 时,即使带有头部信息,它也能正确处理,所以我想知道是否存在 POST 方法的问题,但是我似乎无法解决这个问题。
非常感谢您的帮助。祝好。
英文:
What I want to do
I am creating a Todo app for my Golang studies.
I would like to read the data from POST requests in React with Golang.
Code
go Backend
package todos
import (
"database/sql"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"time"
"todo-app/auth"
"github.com/joho/godotenv"
)
type Todo struct {
// UserID int `json:"userid"`
Todo string `json:"todo"`
CreatedAt time.Time `json:"createdat"`
UpdatedAt time.Time `json:"updatedat"`
}
type TodoBody struct {
Todo string `json:"todo"`
}
func CreateTodo(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "*")
w.Header().Set("Access-Control-Allow-Origin", "http://localhost:3000")
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Allow-Headers", "*")
e := godotenv.Load()
if e != nil {
log.Fatal(e)
}
dbConnectionInfo := fmt.Sprintf("%s:%s@tcp(127.0.0.1:3306)/go_todo", os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"))
db, err := sql.Open("mysql", dbConnectionInfo)
if err != nil {
log.Fatal(err)
}
defer db.Close()
tokenString := r.Header.Get("Authorization")
tokenString = strings.TrimPrefix(tokenString, "Bearer ")
log.Printf("request token=%s\n", tokenString)
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Fatal(err)
}
log.Printf("request body=%s\n", body)
var data TodoBody
if err := json.Unmarshal(body, &data); err != nil {
log.Println(err)
}
// userId := 12
todo := data.Todo
todoData := Todo{todo, time.Now(), time.Now()}
_, err2 := auth.TokenVerify(tokenString)
if err2 != nil {
log.Fatal(err)
} else {
stmt, err := db.Prepare("INSERT INTO todos (Todo,CreatedAt,UpdatedAt) VALUES(?,?,?)")
if err != nil {
log.Fatal(err)
}
_, err = stmt.Exec(todoData.Todo, todoData.CreatedAt, todoData.UpdatedAt)
if err != nil {
log.Fatal(err)
}
json.NewEncoder(w).Encode(todoData)
}
}
React Frontend
import { useState } from "react";
import { useCreateTodo } from "../../hooks/useCreateTodo";
import { BaseButton } from "../atoms/baseButton";
import { TextArea } from "../atoms/textArea";
export const AddTodo = () => {
const [text, setText] = useState("");
const CreateTodo = useCreateTodo();
const token = "Bearer " + sessionStorage.getItem("token");
const onClickCreate = () => {
CreateTodo(token, text);
};
return (
<div>
<TextArea
onChange={(e: any) => setText(e.target.value)}
defaultValue=""
/>
<BaseButton text="タスクを追加" onClick={onClickCreate} />
</div>
);
};
POST here ↓
import axios from "axios";
export const useCreateTodo = () => {
const CreateTodo = (token: string, todo: any) => {
const URL = "http://127.0.0.1:8080/createtodo";
const data = { todo: todo };
console.log(data);
axios
.post(URL, JSON.stringify(data), { headers: { Authorization: token } })
.then((res) => console.log(res))
.catch((err) => console.log(err));
};
return CreateTodo;
};
If I don't add a header when POST the correct value comes to Go's ioutil.ReadAll(r.Body), but if I add a header, I can't get the value.
When I hit Go's API with the Advanced REST client, it is processed correctly even with the header information, so I am wondering if there is a problem with the POST method, but I can't seem to solve the problem.
I would be grateful for your help. Best regards.
答案1
得分: 1
我添加了这段代码,问题得到了解决。
w.Header().Set("Access-Control-Allow-Origin", "http://localhost:3000")
switch r.Method {
case "OPTIONS":
w.Header().Set("Access-Control-Allow-Headers", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
return
感谢您的合作!
英文:
I added this code and it solved the problem..
w.Header().Set("Access-Control-Allow-Origin", "http://localhost:3000")
switch r.Method {
case "OPTIONS":
w.Header().Set("Access-Control-Allow-Headers", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
return
Thanks for your cooperation!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论