本地Go JSON-RPC对接浏览器原生JS报Failed to fetch修复方案
问题解答
本地环境能否实现通信
完全可以。浏览器JS和本地运行的Go服务通过JSON-RPC通信不存在环境层面的限制,你遇到的TypeError: Failed to fetch是代码实现错误导致的,和本地环境无关。
核心错误点
- 协议完全不匹配:你当前写的Go服务是直接在TCP协议层挂载JSON-RPC处理器,根本没有实现HTTP协议解析逻辑。而浏览器
fetchAPI发送的是标准HTTP请求,服务端收到后无法识别HTTP报文格式,自然不会返回符合HTTP规范的响应,直接触发fetch失败。 - 跨域拦截:本地直接打开的HTML文件默认走
file://协议,和http://127.0.0.1:1234属于不同源,就算服务端支持HTTP,没有配置CORS响应头的话,浏览器会直接拦截响应,同样会报fetch错误。 - 前端代码细节错误:你写的请求路径
/rpc/v1在服务端没有对应路由,响应回调里错误引用了未定义的error变量,就算请求通了也拿不到正确结果。
可直接运行的修正代码
Go服务端代码
核心改动是把裸TCP服务改成HTTP服务,增加CORS中间件处理跨域和预检请求,适配HTTP连接到JSON-RPC处理器:
package main import ( "io" "log" "net/http" "net/rpc" "net/rpc/jsonrpc" ) type HelloService struct{} func (p *HelloService) Hello(request string, reply *string) error { *reply = "Hello " + request return nil } // 跨域处理中间件,本地调试用 func corsMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Content-Type") // 处理浏览器跨域预检请求 if r.Method == http.MethodOptions { w.WriteHeader(http.StatusOK) return } next.ServeHTTP(w, r) } } // JSON-RPC HTTP请求处理器 func jsonRPCHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { w.WriteHeader(http.StatusMethodNotAllowed) return } // 包装HTTP连接为JSON-RPC需要的ReadWriteCloser接口 conn := &httpRPCConn{ reader: r.Body, writer: w, } jsonrpc.ServeConn(conn) } type httpRPCConn struct { reader io.Reader writer io.Writer } func (h *httpRPCConn) Read(p []byte) (n int, err error) { return h.reader.Read(p) } func (h *httpRPCConn) Write(p []byte) (n int, err error) { return h.writer.Write(p) } func (h *httpRPCConn) Close() error { if rc, ok := h.reader.(io.Closer); ok { return rc.Close() } return nil } func main() { rpc.RegisterName("HelloService", new(HelloService)) // 注册和前端请求对应的路由 http.HandleFunc("/rpc/v1", corsMiddleware(jsonRPCHandler)) log.Println("RPC服务已启动,监听1234端口") log.Fatal(http.ListenAndServe(":1234", nil)) }
前端client.html代码
修正回调里的变量引用错误,增加结果展示逻辑:
<!DOCTYPE html> <html> <body> <p id="demo">Fetch a file to change this text.</p> <script> fetch('http://127.0.0.1:1234/rpc/v1', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ jsonrpc: '1.0', method: 'HelloService.Hello', params: ["popcontent"], id: "jsonrpc" }) }) .then((response) => { if (!response.ok) { throw new Error(`请求异常,状态码:${response.status}`) } return response.json() }) .then((res) => { console.log("RPC返回结果:", res) document.getElementById('demo').textContent = res.result }) .catch((error) => { console.log("请求错误:", error) }); </script> </body> </html>
运行验证
- 先启动Go服务,控制台会打印服务启动日志
- 直接双击打开client.html,浏览器控制台会输出返回结果
{id: 'jsonrpc', result: 'Hello popcontent', error: null},页面上的文字也会同步替换成返回的内容。
注:代码里的CORS头
Access-Control-Allow-Origin: *仅适合本地调试使用,如果后续把前端部署到正式服务,需要把这个值改成对应前端的域名,避免安全风险。
内容的提问来源于stack exchange,提问作者vanessa boehr
相关产品推荐
相关产品推荐

