http_rest_file/
error.rs

1#[cfg(feature = "rspc")]
2use rspc::Type;
3
4use std::path::PathBuf;
5
6use serde::{Deserialize, Serialize};
7use thiserror::Error;
8
9use crate::model::PartialRequest;
10
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12#[cfg_attr(feature = "rspc", derive(Type))]
13#[derive(Error, Debug, PartialEq, Eq, Clone)]
14pub enum ParseError {
15
16    #[error("Could not read the file: '{0}'.")]
17    CouldNotReadRequestFile(PathBuf),
18
19    #[error("Invalid comment start characters: '{0}', comments before the request url should start with '//', '#' or '###'.")]
20    InvalidCommentStart(String),
21
22    #[error("Invalid request URL found: '{0}'. The URL should either be in the form of an URL using host with optional schemes 'http://', 'https://' or it should be a relative url starting with a slash and the 'Host:' header defined.")]
23    InvalidRequestUrl(String),
24
25    #[error("The HTTP version: '{0}' is not valid. A valid HTTP version requires format: 'HTTP/\\d+.\\d+' or 'HTTP/\\d+'.\nFor example 'HTTP/2.1'. You can also omit the version and only specify the url target of the request or the HTTP method and the url target.")]
26    InvalidHttpVersion(String),
27
28    #[error("Expected either a prerequest script within '{{% %}}' blocks or a filepath to a pre-request script after matching '<' character.")]
29    MissingPreRequestScript,
30    #[error("A pre-request script should be ended with '%}}' characters but none were found.")]
31    MissingPreRequestScriptClose,
32
33    #[error("Missing request target line.")]
34    MissingRequestTargetLine,
35    #[error("The request target line containing the url for the request contains too many elements. There should only be a method, the URL and HTTP version. You have additional elements: {0}")]
36    TooManyElementsOnRequestLine(String),
37
38    #[error("Expected header in the form of '<Key>: <Value>'. Found line: {0}")]
39    InvalidHeaderField(String),
40
41    #[error("Missing multipart boundary in 'Content-Type' for 'multipart/form-data'. Using default boundary '{0}' instead.")]
42    MissingMultipartHeaderBoundaryDefinition(String),
43    #[error("Within multipart body expected either a new boundary starting with '{next_boundary}' or finishing a multipart with '{end_boundary}' but none were found.")]
44    MissingMultipartBoundary {
45        next_boundary: String,
46        end_boundary: String,
47    },
48    #[error("Multipart requires a first starting boundary before any content.")]
49    MissingMultipartStartingBoundary,
50    #[error("Could not parse the headers of the given part of a multipart body. Error during parsing: {error_msg}.")]
51    InvalidSingleMultipartHeaders {
52        header_parse_err: Box<ParseError>,
53        error_msg: String,
54    },
55
56    // first header of a single multipart should be 'Content-Disposition', this error occurs if
57    // none are present
58    #[error("Missing 'Content-Disposition' header of the multipart part.")]
59    MissingSingleMultipartContentDispositionHeader,
60    // If there are headers but the first isn't the 'Content-Disposition' one
61    #[error("First header of a multipart part should be the 'Content-Disposition' header, found '{0}' instead.")]
62    WrongMultipartContentDispositionHeader(String),
63    // 'form-data' is missing, should be the first part of the 'Content-Disposition' header
64    #[error("Multipart Content-Disposition should have type 'form-data', found: {0}.")]
65    InvalidMultipartContentDispositionFormData(String),
66    // The 'Content-Disposition' header is in some way malformed
67    #[error("Expected content disposition values in form <key>=<value> or <key>=\"<value>\" but found: '{0}'")]
68    MalformedContentDispositionEntries(String),
69    // Same as for the request, after the headers an empty line has to occur before the body begins
70    // for every single multipart
71    #[error("Requires empty line in single multipart after Content-Disposition and other headers before the body begins!")]
72    SingleMultipartMissingEmptyLine,
73    #[error("Multipart should be ended with boundary '{0}'. End of file encountered instead.")]
74    MultipartShouldBeEndedWithBoundary(String),
75    #[error("Boundary within multipart content type is required to be 1-70 characters long.")]
76    InvalidMultipartBoundaryLength,
77    #[error("Invalid character: '{0}' found in multipart boundary.")]
78    InvalidMultipartBoundaryCharacter(String),
79    #[error("Content disposition header of a multipart (multipart/formdata) requires a name field, found only {0}")]
80    SingleMultipartNameMissing(String),
81    // response handler opened with '> {% should be closed again
82    #[error("Expected closing '%}}' characters for response handler when opened with '{{%', response handler script is malformed.")]
83    MissingResponseHandlerClose,
84
85    #[error("Missing filepath for response after redirecting file using '>>', or '>>!'")]
86    MissingResponseOutputPath,
87
88    #[error("Could not import collection")]
89    ImportCollectionError,
90
91    //let msg = "Expected pre request starting characters '{%' after a matching '<', or a filepath to a handler script above the request.".to_string();
92    #[error("unknown parse error")]
93    Unknown,
94}
95
96#[derive(Debug, PartialEq, Clone)]
97pub struct ParseErrorDetails {
98    pub error: ParseError,
99    pub details: Option<String>,
100    pub start_pos: Option<usize>,
101    pub end_pos: Option<usize>,
102}
103
104impl Default for ParseErrorDetails {
105    fn default() -> Self {
106        ParseErrorDetails {
107            error: ParseError::Unknown,
108            details: None,
109            start_pos: None,
110            end_pos: None,
111        }
112    }
113}
114
115impl ParseErrorDetails {
116    pub fn new_with_position(error: ParseError, position: (usize, Option<usize>)) -> Self {
117        ParseErrorDetails {
118            error,
119            details: None,
120            start_pos: Some(position.0),
121            end_pos: position.1,
122        }
123    }
124}
125
126impl From<ParseError> for ParseErrorDetails {
127    fn from(parse_error: ParseError) -> Self {
128        ParseErrorDetails {
129            error: parse_error,
130            ..Default::default()
131        }
132    }
133}
134
135#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
136#[derive(Error, Debug, PartialEq, Eq)]
137pub enum SerializeError {
138    #[error("IoError occurred during serialization: {0}")]
139    IoError(String),
140}
141
142#[derive(Debug, PartialEq)]
143pub struct ErrorWithPartial {
144    pub partial_request: PartialRequest,
145    pub details: Vec<ParseErrorDetails>,
146}