Add http_fetch
This commit is contained in:
@@ -154,6 +154,7 @@ For everything else please have a look at the [detailed list][1].
|
||||
- [http_mksession](https://sn0int.readthedocs.io/en/latest/reference.html#http-mksession)
|
||||
- [http_request](https://sn0int.readthedocs.io/en/latest/reference.html#http-request)
|
||||
- [http_send](https://sn0int.readthedocs.io/en/latest/reference.html#http-send)
|
||||
- [http_fetch](https://sn0int.readthedocs.io/en/latest/reference.html#http-fetch)
|
||||
- [http_fetch_json](https://sn0int.readthedocs.io/en/latest/reference.html#http-fetch-json)
|
||||
- [img_load](https://sn0int.readthedocs.io/en/latest/reference.html#img-load)
|
||||
- [img_exif](https://sn0int.readthedocs.io/en/latest/reference.html#img-exif)
|
||||
|
||||
@@ -405,11 +405,31 @@ the following keys:
|
||||
if last_err() then return end
|
||||
if resp['status'] ~= 200 then return 'http status error: ' .. resp['status'] end
|
||||
|
||||
http_fetch
|
||||
----------
|
||||
|
||||
This does an http_send_ and also automatically validate the status code.
|
||||
|
||||
.. note::
|
||||
You almost always want this when setting the ``into_blob`` option since this
|
||||
function validates the status code *before* inserting the response body into
|
||||
blob storage.
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
-- short form
|
||||
data = http_fetch(req)
|
||||
if last_err() then return end
|
||||
|
||||
-- long form
|
||||
resp = http_send(req)
|
||||
if last_err() then return end
|
||||
if resp['status'] ~= 200 then return 'http status error: ' .. resp['status'] end
|
||||
|
||||
http_fetch_json
|
||||
---------------
|
||||
|
||||
This is a shorthand for http_send_, validating the status code and parsing the
|
||||
response body as json.
|
||||
Identical to http_fetch_ but also automatically parses the response body as json.
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
|
||||
@@ -8,11 +8,8 @@ function run()
|
||||
req = http_request(session, 'GET', 'https://www.kernel.org/theme/images/logos/tux.png', {
|
||||
into_blob=true,
|
||||
})
|
||||
r = http_send(req)
|
||||
r = http_fetch(req)
|
||||
if last_err() then return end
|
||||
if r['status'] ~= 200 then
|
||||
return 'http error: ' .. r['status']
|
||||
end
|
||||
|
||||
debug(r)
|
||||
db_add('image', {
|
||||
|
||||
@@ -389,6 +389,7 @@ fn ctx<'a>(env: Environment, logger: Arc<Mutex<Box<Reporter>>>) -> (hlua::Lua<'a
|
||||
runtime::http_mksession(&mut lua, state.clone());
|
||||
runtime::http_request(&mut lua, state.clone());
|
||||
runtime::http_send(&mut lua, state.clone());
|
||||
runtime::http_fetch(&mut lua, state.clone());
|
||||
runtime::http_fetch_json(&mut lua, state.clone());
|
||||
runtime::img_exif(&mut lua, state.clone());
|
||||
runtime::img_load(&mut lua, state.clone());
|
||||
|
||||
@@ -95,9 +95,8 @@ mod tests {
|
||||
req = http_request(session, 'GET', 'https://www.kernel.org/theme/images/logos/tux.png', {
|
||||
into_blob=true,
|
||||
})
|
||||
r = http_send(req)
|
||||
r = http_fetch(req)
|
||||
if last_err() then return end
|
||||
if r['status'] ~= 200 then return 'http error: ' .. r['status'] end
|
||||
|
||||
img = img_load(r['blob'])
|
||||
|
||||
@@ -125,9 +124,8 @@ mod tests {
|
||||
req = http_request(session, 'GET', 'https://www.kernel.org/theme/images/logos/tux.png', {
|
||||
into_blob=true,
|
||||
})
|
||||
r = http_send(req)
|
||||
r = http_fetch(req)
|
||||
if last_err() then return end
|
||||
if r['status'] ~= 200 then return 'http error: ' .. r['status'] end
|
||||
|
||||
nudity = img_nudity(r['blob'])
|
||||
|
||||
@@ -155,10 +153,9 @@ mod tests {
|
||||
req = http_request(session, 'GET', url, {
|
||||
into_blob=true,
|
||||
})
|
||||
r = http_send(req)
|
||||
r = http_fetch(req)
|
||||
if last_err() then return end
|
||||
print(r)
|
||||
if r['status'] ~= 200 then return 'wrong status code' end
|
||||
|
||||
location = img_exif(r['blob'])
|
||||
print(location)
|
||||
|
||||
@@ -31,7 +31,29 @@ pub fn http_send(lua: &mut hlua::Lua, state: Arc<State>) {
|
||||
.context("invalid http request object")
|
||||
.map_err(|err| state.set_error(err.into()))?;
|
||||
|
||||
req.send_lua(state.as_ref())
|
||||
let resp = req.send(state.as_ref())
|
||||
.map_err(|err| state.set_error(err))?;
|
||||
|
||||
req.response_to_lua(state.as_ref(), resp)
|
||||
.map_err(|err| state.set_error(err))
|
||||
.map(|resp| resp.into())
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn http_fetch(lua: &mut hlua::Lua, state: Arc<State>) {
|
||||
lua.set("http_fetch", hlua::function1(move |request: AnyLuaValue| -> Result<AnyLuaValue> {
|
||||
let req = HttpRequest::try_from(request)
|
||||
.context("invalid http request object")
|
||||
.map_err(|err| state.set_error(err.into()))?;
|
||||
|
||||
let resp = req.send(state.as_ref())
|
||||
.map_err(|err| state.set_error(err))?;
|
||||
|
||||
if resp.status < 200 || resp.status > 299 {
|
||||
return Err(state.set_error(format_err!("http status error: {}", resp.status)));
|
||||
}
|
||||
|
||||
req.response_to_lua(state.as_ref(), resp)
|
||||
.map_err(|err| state.set_error(err))
|
||||
.map(|resp| resp.into())
|
||||
}))
|
||||
@@ -167,6 +189,27 @@ mod tests {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn verify_fetch_ok() {
|
||||
let script = Script::load_unchecked(r#"
|
||||
function run()
|
||||
session = http_mksession()
|
||||
req = http_request(session, "GET", "https://httpbin.org/anything", {})
|
||||
x = http_fetch(req)
|
||||
if last_err() then return end
|
||||
|
||||
o = json_decode(x['text'])
|
||||
if last_err() then return end
|
||||
|
||||
if o['method'] ~= 'GET' then
|
||||
return 'unexpected response'
|
||||
end
|
||||
end
|
||||
"#).expect("failed to load script");
|
||||
script.test().expect("Script failed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn verify_fetch_json_ok() {
|
||||
let script = Script::load_unchecked(r#"
|
||||
function run()
|
||||
session = http_mksession()
|
||||
@@ -185,6 +228,19 @@ mod tests {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn verify_fetch_404() {
|
||||
let script = Script::load_unchecked(r#"
|
||||
function run()
|
||||
session = http_mksession()
|
||||
req = http_request(session, "GET", "https://httpbin.org/status/404", {})
|
||||
x = http_fetch(req)
|
||||
end
|
||||
"#).expect("failed to load script");
|
||||
script.test().err().expect("Script should have failed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn verify_fetch_json_404() {
|
||||
let script = Script::load_unchecked(r#"
|
||||
function run()
|
||||
session = http_mksession()
|
||||
@@ -197,7 +253,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn verify_fetch_invalid_json() {
|
||||
fn verify_fetch_json_invalid() {
|
||||
let script = Script::load_unchecked(r#"
|
||||
function run()
|
||||
session = http_mksession()
|
||||
|
||||
21
src/web.rs
21
src/web.rs
@@ -215,27 +215,24 @@ impl HttpRequest {
|
||||
.with_timeout(self.timeout)
|
||||
.wait_for_response()?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn send_lua(&self, state: &State) -> Result<LuaMap> {
|
||||
let res = self.send(state)?;
|
||||
|
||||
// map result to LuaMap
|
||||
let mut resp = LuaMap::new();
|
||||
resp.insert_num("status", f64::from(res.status));
|
||||
|
||||
for cookie in &res.cookies {
|
||||
HttpRequest::register_cookies_on_state(&self.session, state, cookie);
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn response_to_lua(&self, state: &State, res: Response) -> Result<LuaMap> {
|
||||
// map result to LuaMap
|
||||
let mut resp = LuaMap::new();
|
||||
resp.insert_num("status", f64::from(res.status));
|
||||
|
||||
let mut headers = LuaMap::new();
|
||||
for (key, value) in res.headers {
|
||||
headers.insert_str(key.to_lowercase(), value);
|
||||
}
|
||||
resp.insert("headers", headers);
|
||||
|
||||
|
||||
if self.into_blob {
|
||||
let blob = Blob::create(res.body);
|
||||
let id = state.register_blob(blob);
|
||||
@@ -286,6 +283,7 @@ impl Into<AnyLuaValue> for HttpRequest {
|
||||
pub struct CookieJar(HashMap<String, String>);
|
||||
|
||||
impl CookieJar {
|
||||
#[inline(always)]
|
||||
pub fn register_in_jar(&mut self, key: String, value: String) {
|
||||
self.0.insert(key, value);
|
||||
}
|
||||
@@ -294,6 +292,7 @@ impl CookieJar {
|
||||
impl Deref for CookieJar {
|
||||
type Target = HashMap<String, String>;
|
||||
|
||||
#[inline(always)]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user