sn0int 0.12.0

Semi-automatic OSINT framework and package manager
Documentation
use crate::errors::*;

use crate::engine::ctx::State;
use crate::hlua::{self, AnyLuaValue, AnyHashableLuaValue};
use std::sync::Arc;
use std::collections::HashMap;
use crate::web::{RequestOptions, HttpRequest};


pub fn http_mksession(lua: &mut hlua::Lua, state: Arc<State>) {
    lua.set("http_mksession", hlua::function0(move || -> String {
        state.http_mksession()
    }))
}

pub fn http_request(lua: &mut hlua::Lua, state: Arc<State>) {
    lua.set("http_request", hlua::function4(move |session: String, method: String, url: String, options: AnyLuaValue| -> Result<AnyLuaValue> {
        RequestOptions::try_from(options)
            .context("invalid request options")
            .map_err(|err| state.set_error(Error::from(err)))
            .map(|options| {
                state.http_request(&session, method, url, options).into()
            })
    }))
}

pub fn http_send(lua: &mut hlua::Lua, state: Arc<State>) {
    lua.set("http_send", hlua::function1(move |request: AnyLuaValue| -> Result<HashMap<AnyHashableLuaValue, AnyLuaValue>> {
        let req = match HttpRequest::try_from(request)
                                .context("invalid http request object") {
            Ok(req) => req,
            Err(err) => return Err(state.set_error(Error::from(err))),
        };

        req.send(state.as_ref())
            .map_err(|err| state.set_error(err))
            .map(|resp| resp.into())
    }))
}


#[cfg(test)]
mod tests {
    use crate::engine::ctx::Script;
    use std::time::{Instant, Duration};

    #[test]
    #[ignore]
    fn verify_request() {
        let script = Script::load_unchecked(r#"
        function run()
            session = http_mksession()
            req = http_request(session, "GET", "https://httpbin.org/anything", {})
            x = http_send(req)
            if last_err() then return end
            print(x)

            if x['status'] ~= 200 then
                return 'wrong status code'
            end
        end
        "#).expect("failed to load script");
        script.test().expect("Script failed");
    }

    #[test]
    #[ignore]
    fn verify_timeout() {
        let start = Instant::now();
        let script = Script::load_unchecked(r#"
        function run()
            session = http_mksession()
            req = http_request(session, "GET", "http://1.2.3.4", {
                timeout=250
            })
            x = http_send(req)
            if last_err() then return end
        end
        "#).expect("failed to load script");
        script.test().err().expect("Script should have failed");
        let end = Instant::now();

        assert!(end.duration_since(start) < Duration::from_secs(1));
    }

    #[test]
    #[ignore]
    fn verify_post() {
        let script = Script::load_unchecked(r#"
        function run()
            session = http_mksession()

            headers = {}
            headers['Content-Type'] = "application/json"
            req = http_request(session, "POST", "https://httpbin.org/anything", {
                headers=headers,
                query={
                    foo="bar"
                },
                json={
                    hello="world"
                }
            })
            x = http_send(req)
            if last_err() then return end
            print(x)

            o = json_decode(x['text'])
            if last_err() then return end

            if o['args']['foo'] ~= 'bar' or o['json']['hello'] ~= 'world' then
                return "reply didn't contain all params"
            end
        end
        "#).expect("failed to load script");
        script.test().expect("Script failed");
    }

    #[test]
    #[ignore]
    fn verify_cookies() {
        let script = Script::load_unchecked(r#"
        function run()
            session = http_mksession()

            req = http_request(session, "GET", "https://httpbin.org/cookies/set", {
                query={
                    foo="bar",
                    fizz="buzz"
                }
            })
            x = http_send(req)

            req = http_request(session, "GET", "https://httpbin.org/cookies", {})
            x = http_send(req)
            if last_err() then return end
            print(x)

            o = json_decode(x['text'])
            if last_err() then return end

            if o['cookies']['fizz'] ~= 'buzz' or o['cookies']['foo'] ~= 'bar' then
                return "reply didn't contain all cookies"
            end
        end
        "#).expect("failed to load script");
        script.test().expect("Script failed");
    }
}