Skip to main content

fastcgi_client/
error.rs

1// Copyright 2022 jmjoy
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Error types and result type aliases for FastCGI operations.
16//!
17//! This module defines the error types that can occur during FastCGI
18//! communication and provides convenient type aliases for results.
19
20use crate::meta::{ProtocolStatus, RequestType};
21
22/// Result type alias for FastCGI client operations.
23pub type ClientResult<T> = Result<T, ClientError>;
24
25/// Result type alias for HTTP/FastCGI conversion operations.
26#[cfg(feature = "http")]
27pub type HttpConversionResult<T> = Result<T, HttpConversionError>;
28
29/// Error types that can occur during FastCGI communication.
30#[derive(Debug, thiserror::Error)]
31pub enum ClientError {
32    /// Wrapper of `std::io::Error`
33    #[error(transparent)]
34    Io(#[from] std::io::Error),
35
36    /// Usually not happen.
37    #[error("Response not found of request id `{id}`")]
38    RequestIdNotFound {
39        /// The request ID that was not found
40        id: u16,
41    },
42
43    /// Usually not happen.
44    #[error("Response not found of request id `{id}`")]
45    ResponseNotFound {
46        /// The request ID for which no response was found
47        id: u16,
48    },
49
50    /// Maybe unimplemented request type received fom response.
51    #[error("Response not found of request id `{request_type}`")]
52    UnknownRequestType {
53        /// The unknown request type received
54        request_type: RequestType,
55    },
56
57    /// Response not complete, first is protocol status and second is app
58    /// status, see fastcgi protocol.
59    #[error("This app can't multiplex [CantMpxConn]; AppStatus: {app_status}")]
60    EndRequestCantMpxConn {
61        /// The application status code
62        app_status: u32,
63    },
64
65    /// Response not complete, first is protocol status and second is app
66    /// status, see fastcgi protocol.
67    #[error("New request rejected; too busy [OVERLOADED]; AppStatus: {app_status}")]
68    EndRequestOverloaded {
69        /// The application status code
70        app_status: u32,
71    },
72
73    /// Response not complete, first is protocol status and second is app
74    /// status, see fastcgi protocol.
75    #[error("Role value not known [UnknownRole]; AppStatus: {app_status}")]
76    EndRequestUnknownRole {
77        /// The application status code
78        app_status: u32,
79    },
80}
81
82/// Error types that can occur while converting between FastCGI and HTTP types.
83#[cfg(feature = "http")]
84#[derive(Debug, thiserror::Error)]
85pub enum HttpConversionError {
86    /// Required FastCGI param is missing during HTTP conversion.
87    #[error("Missing FastCGI param `{name}`")]
88    MissingFastcgiParam {
89        /// The missing FastCGI param name.
90        name: &'static str,
91    },
92
93    /// Invalid HTTP method during conversion.
94    #[error(transparent)]
95    InvalidHttpMethod(#[from] ::http::method::InvalidMethod),
96
97    /// Invalid HTTP URI during conversion.
98    #[error(transparent)]
99    InvalidHttpUri(#[from] ::http::uri::InvalidUri),
100
101    /// Invalid HTTP header name during conversion.
102    #[error(transparent)]
103    InvalidHttpHeaderName(#[from] ::http::header::InvalidHeaderName),
104
105    /// Invalid HTTP header value during conversion.
106    #[error(transparent)]
107    InvalidHttpHeaderValue(#[from] ::http::header::InvalidHeaderValue),
108
109    /// Invalid HTTP status code during conversion.
110    #[error(transparent)]
111    InvalidHttpStatusCode(#[from] ::http::status::InvalidStatusCode),
112
113    /// Invalid HTTP message constructed by builder.
114    #[error(transparent)]
115    InvalidHttpMessage(#[from] ::http::Error),
116
117    /// CGI response payload could not be parsed into headers and body.
118    #[error("Malformed CGI response: {message}")]
119    MalformedHttpResponse {
120        /// Human-readable parse failure reason.
121        message: &'static str,
122    },
123}
124
125impl ClientError {
126    /// Creates a new end request error based on the protocol status.
127    ///
128    /// # Arguments
129    ///
130    /// * `protocol_status` - The protocol status returned by the FastCGI server
131    /// * `app_status` - The application status code
132    pub(crate) fn new_end_request_with_protocol_status(
133        protocol_status: ProtocolStatus, app_status: u32,
134    ) -> Self {
135        match protocol_status {
136            ProtocolStatus::CantMpxConn => ClientError::EndRequestCantMpxConn { app_status },
137            ProtocolStatus::Overloaded => ClientError::EndRequestOverloaded { app_status },
138            _ => ClientError::EndRequestUnknownRole { app_status },
139        }
140    }
141}