Addition of the gemini feature as well as Url, wrap_url and unwrap_url.

This commit is contained in:
abbie 2022-03-12 20:49:48 +00:00
parent 7d5530370f
commit 6c4028e48c
No known key found for this signature in database
GPG key ID: 04DDE463F9200F87
3 changed files with 124 additions and 1 deletions

View file

@ -1,7 +1,7 @@
[package]
name = "packeteer"
description = "An attempt at a Rust library that can be used to assist in programmatically analysing, serving and handling received protocol packets."
version = "0.1.4"
version = "0.2.0"
edition = "2021"
authors = ["Celeste <colean@colean.cc>"]
license = "LGPL-3.0-or-later"
@ -16,5 +16,6 @@ all-features = true
[features]
http1 = []
gemini = []
[dependencies]

85
src/gemini.rs Normal file
View file

@ -0,0 +1,85 @@
//! A module for handling Gemini operations.
//! It contains structures for Gemini requests and responses as well as functions for generating, unpacking and constructing them.
use super::{Url, wrap_url, unwrap_url};
use std::str::FromStr;
// A structure for Gemini requests.
// Generated with packeteer::gemini::generate_request
#[derive(Debug)]
pub struct GeminiRequest {
pub url: Url,
}
// A structure for Gemini responses.
// Generated with packeteer::gemini::generate_response
#[derive(Debug)]
pub struct GeminiResponse {
pub code: i32,
pub meta: String,
pub body: String,
}
// A function for generating GeminiRequest structures.
pub fn generate_request(url: &str) -> GeminiRequest {
let wurl = wrap_url(url);
let gem = GeminiRequest { url: wurl };
return gem
}
// A function for generating GeminiResponse structures.
// Any invalid status code (valid status codes are 69 > x >= 10) will automatically be switched to 40 (Temporary failure).
pub fn generate_response(code: i32, body: &str) -> GeminiResponse {
let mut xcode = code;
if code < 10 { xcode = 40 };
if code > 69 { xcode = 40 };
let res = GeminiResponse { code: xcode, meta: "".to_string(), body: body.to_string() };
return res
}
// A function for converting GeminiRequest structures into a Gemini request string.
// This is extremely simple since GeminiRequest is basically storing a Url.
// Unpacking functions are simply taking the data stored in the structure and concatenating it into a string so nothing changes apart from the conversion.
pub fn unpack_request(req: GeminiRequest) -> String {
let url = unwrap_url(req.url);
let string = format!("{}\r\n", url);
return string.to_string()
}
// A function for converting GeminiResponse structures into split header and body strings.
// The header and body are split as the Gemini specification seperates them.
// Unpacking functions are simply taking the data stored in the structure and concatenating it into a string so nothing changes apart from the conversion.
pub fn unpack_response(res: GeminiResponse) -> (String, String) {
let string = format!("{} {}\r\n", res.code, res.meta);
return (string.to_string(), res.body)
}
// A function for converting Gemini request strings into GeminiRequest.
// This is essentially equivalent to packeteer::gemini::generate_request apart from the fact it automatically removes the character return and line feed after the URL to allow for conversion from raw Gemini requests.
// Construction functions aim to be as transparent as possible so apart from turning it into a structure, the request stays relatively unchanged.
pub fn construct_request(req: &str) -> GeminiRequest {
let url: Vec<&str> = req.split("\r\n").collect();
let wurl = wrap_url(url[0]);
let gem = GeminiRequest { url: wurl };
return gem
}
// A function for converting Gemini header and body strings into GeminiResponse.
// Construction functions aim to be as transparent as possible so apart from turning it into a structure, the response stays relatively unchanged.
pub fn construct_response(res: &str, body: &str) -> GeminiResponse {
let split1: Vec<&str> = res.split("\r\n").collect();
let split2: Vec<&str> = split1[0].split(" ").collect();
let mut meta = "".to_string();
for v in &split2 {
if v != &split2[0] {
if meta == "" {
meta = v.to_string();
} else {
meta = format!("{} {}", meta, v.to_string());
}
}
}
let n: i32 = FromStr::from_str(split2[0]).unwrap();
let resp = GeminiResponse { code: n, meta: meta.to_string(), body: body.to_string() };
return resp
}

View file

@ -43,5 +43,42 @@ pub fn generate_kvheader(key: &str, value: &str) -> KVHeader {
return result
}
/// A global structure for integrating URLs within the structural system of packeteer.
/// Can be automatically generated with the function packeteer::wrap_url.
#[derive(Debug)]
pub struct Url {
pub protocol: String,
pub domain: String,
pub segments: Vec<String>,
}
/// A public function for wrapping a string reference as a Url structure.
pub fn wrap_url(input: &str) -> Url {
let split1: Vec<&str> = input.split("://").collect();
let split2: Vec<&str> = split1[1].split("/").collect();
let protocol = split1[0];
let domain = split2[0];
let mut segments: Vec<String> = vec![];
for v in split2 {
if v != "" && v != domain {
segments.push(v.to_string());
}
}
let url = Url { protocol: protocol.to_string(), domain: domain.to_string(), segments: segments };
return url
}
/// A public function for unwrapping a Url structure into a String.
pub fn unwrap_url(input: Url) -> String {
let mut string = format!("{}://{}", input.protocol, input.domain);
for v in input.segments {
string = format!("{}/{}", string, v);
}
return string.to_string();
}
#[cfg(feature = "http1")]
pub mod http1;
#[cfg(feature = "gemini")]
pub mod gemini;