H-170: parse Shangwutong send error header (#28)

Co-authored-by: Rogee <rogee@ipao.vip>
This commit is contained in:
Rogee
2026-08-15 11:48:49 +08:00
committed by GitHub
co-authored by rogee
parent 18ecee3e46
commit 2d1b9ab5a7
2 changed files with 43 additions and 4 deletions
+9 -4
View File
@@ -197,13 +197,18 @@ func (c *Client) sendHTML(ctx context.Context, session Session, sid, content, op
}
return SendResult{}, &Error{Operation: operation, Code: "network_error", Retryable: true, Err: err}
}
status := response.Header.Get("r")
status := strings.TrimSpace(response.Header.Get("r"))
if !strings.EqualFold(status, "ok") {
if protocolError := strings.TrimSpace(response.Header.Get("error")); protocolError != "" {
status = protocolError
}
}
result := SendResult{Status: status, Body: body}
if status == "ok" {
if strings.EqualFold(status, "ok") {
return result, nil
}
retryable := status == "server err"
return result, &Error{Operation: operation, Code: normalizeCode(status), Retryable: retryable}
code := normalizeCode(status)
return result, &Error{Operation: operation, Code: code, Retryable: code == "server_err"}
}
func (c *Client) SetPresence(ctx context.Context, session Session, presence Presence) error {
@@ -68,6 +68,40 @@ func TestClientSendTextEscapesHTML(t *testing.T) {
}
}
func TestClientSendTextClassifiesProtocolStatus(t *testing.T) {
tests := []struct {
name, status, protocolError, wantCode string
wantRetryable bool
}{
{name: "success", status: "ok"},
{name: "explicit failure", status: "failed", wantCode: "failed"},
{name: "error header", protocolError: "state err", wantCode: "state_err"},
{name: "retryable error", protocolError: "server err", wantCode: "server_err", wantRetryable: true},
{name: "missing status", wantCode: "missing_status"},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, _ *http.Request) {
response.Header().Set("r", test.status)
response.Header().Set("error", test.protocolError)
}))
defer server.Close()
result, err := NewClient(rewriteTransportClient(server.URL)).SendText(context.Background(), testSession(), "sid", "hello")
if test.wantCode == "" {
if err != nil || result.Status != "ok" {
t.Fatalf("result = %#v, error = %v", result, err)
}
return
}
var protocolErr *Error
if !errors.As(err, &protocolErr) || protocolErr.Code != test.wantCode || protocolErr.Retryable != test.wantRetryable {
t.Fatalf("result = %#v, error = %#v", result, err)
}
})
}
}
func TestClientSendFailureBeforeRequestWriteIsRetryable(t *testing.T) {
client := NewClient(&http.Client{Transport: roundTripFunc(func(*http.Request) (*http.Response, error) {
return nil, errors.New("connection lost")