<commit_before>use tracker::Tracker;
use response::TrackerResponse;
use response::error::ErrorResponse;
use response::success::SuccessResponse;
use tracker::announce::{Action, Announce};
use tracker::scrape::Scrape;

use hyper::server::{Request, Response, Handler};
use hyper::uri::RequestUri::AbsolutePath;
use std::net::{IpAddr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::collections::HashMap;
use std::sync::Arc;
use url::form_urlencoded;
use url::{Url, UrlParser};
use std::str::FromStr;
use std::cmp;

pub struct RequestHandler {
    pub tracker: Arc<Tracker>,
}

impl RequestHandler {
    pub fn new(tracker: Arc<Tracker>) -> RequestHandler {
        RequestHandler { tracker: tracker }
    }
}

impl Handler for RequestHandler {
    fn handle(&self, req: Request, res: Response) {
        let resp = match req.uri {
            AbsolutePath(ref path) => {
                let base = Url::parse("http://localhost").unwrap();
                let url = UrlParser::new().base_url(&base).parse(path).unwrap();
                self.handle_url(&req, url)
            }
            _ => Err(ErrorResponse::BadAction),
        };
        res.send(serialize_resp(resp).as_slice()).unwrap();
    }
}

impl RequestHandler {
    fn handle_url(&self, req: &Request, url: Url) -> Result<SuccessResponse, ErrorResponse> {
        if url.path().is_none() {
            return Err(ErrorResponse::BadAction);
        }
        let path = url.path().unwrap();
        let params = url.query_pairs();

        if cfg!(feature = "private") {
            if path.len() != 2 {
                Err(ErrorResponse::BadRequest)
            } else {
                self.handle_private_req(&path[1], &path[0], params)
            }
        } else {
            if path.len() != 1 {
                Err(ErrorResponse::BadRequest)
            } else {
                self.handle_public_req(req, &path[0], params)
            }
        }
    }

    fn handle_public_req(&self,
                         req: &Request,
                         path: &String,
                         params: Option<Vec<(String, String)>>)
                         -> Result<SuccessResponse, ErrorResponse> {
        match &path[..] {
            "stats" => self.tracker.get_stats(),
            "announce" => {
                let announce = try!(request_to_announce(req, params));
                self.tracker.handle_announce(announce)
            }
            "scrape" => {
                let scrape = try!(request_to_scrape(params));
                self.tracker.handle_scrape(scrape)
            }
            _ => Err(ErrorResponse::BadAction),
        }
    }

    fn handle_private_req(&self,
                          path: &String,
                          key: &String,
                          params: Option<Vec<(String, String)>>)
                          -> Result<SuccessResponse, ErrorResponse> {
        Err(ErrorResponse::BadAction)
    }
}

fn request_to_scrape(params: Option<Vec<(String, String)>>) -> Result<Scrape, ErrorResponse> {
    if params.is_none() {
        return Err(ErrorResponse::BadRequest);<commit_msg>Some minor tweaks to tracker request handling<commit_after>use tracker::Tracker;
use response::TrackerResponse;
use response::error::ErrorResponse;
use response::success::SuccessResponse;
use tracker::announce::{Action, Announce};
use tracker::scrape::Scrape;

use hyper::server::{Request, Response, Handler};
use hyper::uri::RequestUri::AbsolutePath;
use std::net::{IpAddr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::collections::HashMap;
use std::sync::Arc;
use url::{Url, UrlParser};
use std::str::FromStr;
use std::cmp;

pub struct RequestHandler {
    pub tracker: Arc<Tracker>,
}

impl RequestHandler {
    pub fn new(tracker: Arc<Tracker>) -> RequestHandler {
        RequestHandler { tracker: tracker }
    }
}

impl Handler for RequestHandler {
    fn handle(&self, req: Request, res: Response) {
        let resp = match req.uri {
            AbsolutePath(ref path) => {
                let base = Url::parse("http://localhost").unwrap();
                let url = UrlParser::new().base_url(&base).parse(path).unwrap();
                self.handle_url(&req, url)
            }
            _ => Err(ErrorResponse::BadAction),
        };
        res.send(serialize_resp(resp).as_slice()).unwrap();
    }
}

impl RequestHandler {
    fn handle_url(&self, req: &Request, url: Url) -> Result<SuccessResponse, ErrorResponse> {
        if url.path().is_none() {
            return Err(ErrorResponse::BadAction);
        }
        let path = url.path().unwrap();
        let params = url.query_pairs();

        if cfg!(feature = "private") {
            if path.len() != 2 {
                Err(ErrorResponse::BadRequest)
            } else {
                // Do key validation
                if false {
                    Err(ErrorResponse::BadAuth)
                } else {
                    self.handle_req(req, &path[1], params)
                }
            }
        } else {
            if path.len() != 1 {
                Err(ErrorResponse::BadRequest)
            } else {
                self.handle_req(req, &path[0], params)
            }
        }
    }

    fn handle_req(&self,
                  req: &Request,
                  path: &String,
                  params: Option<Vec<(String, String)>>)
                  -> Result<SuccessResponse, ErrorResponse> {
        match &path[..] {
            "stats" => self.tracker.get_stats(),
            "announce" => {
                let announce = try!(request_to_announce(req, params));
                self.tracker.handle_announce(announce)
            }
            "scrape" => {
                let scrape = try!(request_to_scrape(params));
                self.tracker.handle_scrape(scrape)
            }
            _ => Err(ErrorResponse::BadAction),
        }
    }
}

fn request_to_scrape(params: Option<Vec<(String, String)>>) -> Result<Scrape, ErrorResponse> {
    if params.is_none() {
        return Err(ErrorResponse::BadRequest);
{'fraction_non_alphanumeric': 0.1337421279416639, 'fraction_numerical': 0.002154458070931389, 'mean_word_length': 2.047979797979798, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1597323', 'n_tokens_mistral': 1750, 'n_tokens_neox': 1686, 'n_words': 334}