60 lines
1.7 KiB
Go
60 lines
1.7 KiB
Go
package oci
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/json"
|
||
"io"
|
||
"net/http"
|
||
|
||
"github.com/oracle/oci-go-sdk/v65/common"
|
||
)
|
||
|
||
// scimErrorDispatcher 包装 Identity Domains 客户端的 HTTP 派发器。
|
||
// IDCS 的错误体是 SCIM 格式(detail 字段),而 SDK 只解析 code/message,
|
||
// 直接透传会得到消息为空的 BadErrorResponse;这里把 4xx/5xx 的 SCIM
|
||
// 错误体改写成 SDK 可解析的标准形状,让真实原因透出到面板。
|
||
type scimErrorDispatcher struct {
|
||
base common.HTTPRequestDispatcher
|
||
}
|
||
|
||
func (d scimErrorDispatcher) Do(req *http.Request) (*http.Response, error) {
|
||
resp, err := d.base.Do(req)
|
||
if err != nil || resp == nil || resp.StatusCode < 400 || resp.Body == nil {
|
||
return resp, err
|
||
}
|
||
body, readErr := io.ReadAll(resp.Body)
|
||
resp.Body.Close()
|
||
if readErr != nil {
|
||
resp.Body = io.NopCloser(bytes.NewReader(nil))
|
||
return resp, nil
|
||
}
|
||
rewritten := rewriteScimError(body)
|
||
resp.Body = io.NopCloser(bytes.NewReader(rewritten))
|
||
resp.ContentLength = int64(len(rewritten))
|
||
resp.Header.Del("Content-Length")
|
||
return resp, nil
|
||
}
|
||
|
||
// rewriteScimError 提取 SCIM 错误的 detail 与 messageId 转成
|
||
// {code,message};不是 SCIM 错误体时原样返回。
|
||
func rewriteScimError(body []byte) []byte {
|
||
var scim struct {
|
||
Detail string `json:"detail"`
|
||
Ext struct {
|
||
MessageID string `json:"messageId"`
|
||
} `json:"urn:ietf:params:scim:api:oracle:idcs:extension:messages:Error"`
|
||
}
|
||
if json.Unmarshal(body, &scim) != nil || scim.Detail == "" {
|
||
return body
|
||
}
|
||
code := scim.Ext.MessageID
|
||
if code == "" {
|
||
code = "IdcsError"
|
||
}
|
||
std, err := json.Marshal(map[string]string{"code": code, "message": scim.Detail})
|
||
if err != nil {
|
||
return body
|
||
}
|
||
return std
|
||
}
|