1use nu_engine::{command_prelude::*, get_full_help};
2
3use super::get::run_get;
4use super::post::run_post;
5
6#[derive(Clone)]
7pub struct Http;
8
9impl Command for Http {
10 fn name(&self) -> &str {
11 "http"
12 }
13
14 fn signature(&self) -> Signature {
15 Signature::build("http")
16 .input_output_types(vec![(Type::Nothing, Type::Any)])
17 .optional(
19 "URL",
20 SyntaxShape::String,
21 "The URL to fetch the contents from.",
22 )
23 .optional(
25 "data",
26 SyntaxShape::Any,
27 "The contents of the post body. Required unless part of a pipeline.",
28 )
29 .named(
30 "content-type",
31 SyntaxShape::Any,
32 "the MIME type of content to post",
33 Some('t'),
34 )
35 .named(
37 "user",
38 SyntaxShape::Any,
39 "the username when authenticating",
40 Some('u'),
41 )
42 .named(
43 "password",
44 SyntaxShape::Any,
45 "the password when authenticating",
46 Some('p'),
47 )
48 .named(
49 "max-time",
50 SyntaxShape::Duration,
51 "max duration before timeout occurs",
52 Some('m'),
53 )
54 .named(
55 "headers",
56 SyntaxShape::Any,
57 "custom headers you want to add ",
58 Some('H'),
59 )
60 .switch(
61 "raw",
62 "fetch contents as text rather than a table",
63 Some('r'),
64 )
65 .switch(
66 "insecure",
67 "allow insecure server connections when using SSL",
68 Some('k'),
69 )
70 .switch(
71 "full",
72 "returns the full response instead of only the body",
73 Some('f'),
74 )
75 .switch(
76 "allow-errors",
77 "do not fail if the server returns an error code",
78 Some('e'),
79 )
80 .named(
81 "redirect-mode",
82 SyntaxShape::String,
83 "What to do when encountering redirects. Default: 'follow'. Valid options: 'follow' ('f'), 'manual' ('m'), 'error' ('e').",
84 Some('R')
85 )
86 .category(Category::Network)
87 }
88
89 fn description(&self) -> &str {
90 "Various commands for working with http methods."
91 }
92
93 fn extra_description(&self) -> &str {
94 "Without a subcommand but with a URL provided, it performs a GET request by default or a POST request if data is provided. You can use one of the following subcommands. Using this command as-is will only display this help message."
95 }
96
97 fn search_terms(&self) -> Vec<&str> {
98 vec![
99 "network", "fetch", "pull", "request", "download", "curl", "wget",
100 ]
101 }
102
103 fn run(
104 &self,
105 engine_state: &EngineState,
106 stack: &mut Stack,
107 call: &Call,
108 input: PipelineData,
109 ) -> Result<PipelineData, ShellError> {
110 let url = call.opt::<Value>(engine_state, stack, 0)?;
111 let data = call.opt::<Value>(engine_state, stack, 1)?;
112 match (url.is_some(), data.is_some()) {
113 (true, true) => run_post(engine_state, stack, call, input),
114 (true, false) => run_get(engine_state, stack, call, input),
115 (false, true) => Err(ShellError::NushellFailed {
116 msg: (String::from("Default verb is get with a payload. Impossible state")),
117 }),
118 (false, false) => Ok(Value::string(
119 get_full_help(self, engine_state, stack),
120 call.head,
121 )
122 .into_pipeline_data()),
123 }
124 }
125
126 fn examples(&self) -> Vec<Example> {
127 vec![
128 Example {
129 description: "Get content from example.com with default verb",
130 example: "http https://www.example.com",
131 result: None,
132 },
133 Example {
134 description: "Post content to example.com with default verb",
135 example: "http https://www.example.com 'body'",
136 result: None,
137 },
138 Example {
139 description: "Get content from example.com with explicit verb",
140 example: "http get https://www.example.com",
141 result: None,
142 },
143 ]
144 }
145}