[dependencies]
hyper = "0.12"
serde_json = "1.0.96"
futures = "0.1.31"
lazy_static = "1.4.0"
rust-crypto = "0.2.36"
pretty_env_logger = "0.5"
log = "0.4"
// hyperurl/src/index.rs
pub static INDEX_PAGE: &str = r##"
hyperurl - A url shortener in Rust
hyperurl - A url shortening service
To shorten a url, make a post request using curl as:
curl --data "https://creativcoder.github.io" http://localhost:3002/shorten
You will get a reply as:
{
"127.0.0.1:3002/992a7": "https://creativcoder.github.io"
}
Put the shortened url (127.0.0.1:3002/992a7) in the browser to get redirected to the original website.
Made with with hyper in Rust
"##;
// hyperurl/src/service.rs
use std::sync::RwLock;
use std::collections::HashMap;
use std::sync::{Arc};
use std::str;
use hyper::Request;
use hyper::{Body, Response};
use hyper::rt::{Future, Stream};
use hyper::Method;
use hyper::StatusCode;
use lazy_static::lazy_static;
use log::info;
use crate::shortener::shorten_url;
use futures::future;
use crate::index::INDEX_PAGE;
use crate::LISTEN_ADDR;
type UrlDb = Arc>>;
type BoxFut = Box, Error = hyper::Error> + Send>;
lazy_static! {
static ref SHORT_URLS: UrlDb = Arc::new(RwLock::new(HashMap::new()));
}
pub(crate) fn url_service(req: Request) -> BoxFut {
match (req.method(), req.uri().path()) {
(&Method::GET, "/") => {
let reply = Response::new(Body::from(format!("{}",INDEX_PAGE)));
Box::new(future::ok(reply))
}
(&Method::GET, _) => {
let url_db = SHORT_URLS.read().unwrap();
let uri = req.uri().to_string();
let short_url = format!("{}{}", LISTEN_ADDR, uri);
let long_url = url_db.get(&short_url);
println!("LONG URL {:?}",long_url);
let reply = match long_url {
Some(url) => {
info!("Redirecting from {} to {}", short_url, url);
Response::builder().status(StatusCode::TEMPORARY_REDIRECT)
.header("Location", url.to_string()).body(Body::empty()).unwrap()
}
None => {
Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::from(format!("Bad URI: {:?}", uri))).unwrap()
}
};
Box::new(future::ok(reply))
}
(&Method::POST, "/shorten") => {
info!("Received request from : {:?}", req.headers());
let reply = req.into_body().concat2().map(move |chunk| {
let c = chunk.iter().cloned().collect::>();
let url_to_shorten = str::from_utf8(&c).unwrap();
let short_url = shorten_url(url_to_shorten);
let reply = Response::new(Body::from(format!("{}", &short_url)));
SHORT_URLS.write().unwrap().insert(short_url, url_to_shorten.to_string());
reply
});
Box::new(reply)
}
(_, _) => {
let no_route = Response::new(Body::from("No route handler for this path"));
Box::new(future::ok(no_route))
}
}
}
// hyperurl/src/shortener.rs
use crypto::digest::Digest;
use crypto::sha2::Sha256;
use crate::LISTEN_ADDR;
pub(crate) fn shorten_url(url: &str) -> String {
let mut sha = Sha256::new();
sha.input_str(url);
let mut s = sha.result_str();
s.truncate(5);
format!("{}/{}", LISTEN_ADDR, s)
}
// hyperurl/src/main.rs
use log::{info, error};
use std::env;
use hyper::Server;
use hyper::service::service_fn;
use hyper::rt::{self, Future};
mod shortener;
mod service;
mod index;
use crate::service::url_service;
const LISTEN_ADDR: &str = "127.0.0.1:3002";
fn main() {
env::set_var("RUST_LOG","hyperurl=info");
pretty_env_logger::init();
let addr = LISTEN_ADDR.parse().unwrap();
let server = Server::bind(&addr)
.serve(|| service_fn(url_service))
.map_err(|e| error!("server error: {}", e));
info!("hyperurl is listening at {}", addr);
rt::run(server);
}
页面更新:2024-02-22
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号