目录
这个问题来源于我在开启kubectl proxy代理的时候,通过kubectl apply -f xxx.yaml向代理提交一个configMap对象,返回了 "Error while proxying request: invalid character '\x1f' looking for beginning of value" 的报错。
我通过打印请求,得到了 kubectl apply -f xxx.yaml 的基本流程:
通过查询这个问题出现的原因得知,出现的原因是解析接口返回的字节符切片错误,出现了一堆乱码。解析失败是因为请求在 Header 里加入了Accept-Encoding: gzip,导致返回的结果被 gzip 压缩,然后返回的结果无法通过正常的 ioUtil.ReadAll(rsp.Body) 取出的内容去反序列化。
具体的解决手法参考见 invalid character '\x1f' looking for beginning of value
沿着这个思路,我在开启的代理代码里面发现了一段返回结果的拦截
func (mtp *MyTransport) RoundTrip(req *http.Request) (*http.Response, error) {
rsp, err := mtp.RoundTripper.RoundTrip(req)
if err != nil {
return nil, err
}
defer rsp.Body.Close()
b, err := ioutil.ReadAll(rsp.Body) //读取后,rsp body内容将就空了。需要重新赋值回去
if err != nil {
return nil, err
}
//序列化对象
obj := unstructured.Unstructured{}
if err = obj.UnmarshalJSON(b); err == nil {
addCustomColumn(&obj, req)
b, err = obj.MarshalJSON()
if err != nil {
return nil, err
}
} else {
return nil, err
}
rsp.Body = ioutil.NopCloser(bytes.NewReader(b)) //tips 给body赋值的方法
fmt.Println("响应对象类型:" + obj.GetKind())
rsp.Header.Set("Content-Length", strconv.Itoa(len(b))) //这个很重要,如果修改了body内容需要重新计算长度
return rsp, nil
}
原因是因为我需要在 kubectl get xxx 的时候对返回的结果反序列后修订内容,再序列化后返回。
参考网上的解决方法,方法一是删除 Header 中的 Accept-Encoding: gzip,方法二是添加一段读取 gzip 压缩内容 Body 的代码
if req.Header.Get("Accept-Encoding") == "gzip" {
gr, err = gzip.NewReader(rsp.Body)
if err != nil {
return nil, err
}
}
两种方法都没能成功,同样返回 "invalid character '\x03' looking for beginning of value"。
最后想到了,我其实并不需要为 /openapi/v2 这类的请求加工处理返回结果,所以只要跳过反序列化就可以,因此在 RoundTrip 中加入
//针对openapi做处理
if regexp.MustCompile(OpenApiPattern).MatchString(req.RequestURI) {
return rsp, nil
}
最后 kubectl apply -f xxx.yaml 测试 ,通过。