hyper
HTTP/2 for Python.
Hyper: HTTP/2 Client for Python — hyper 0.4.0 documentation
I am trying to run the hyper example listed on the Github readme.
extern crate hyper;
use std::io::Write;
use hyper::Server;
use hyper::server::Request;
use hyper::server::Response;
use hyper::net::Fresh;
fn hello(_: Request, res: Response<Fresh>) {
let mut res = res.start().unwrap();
res.write_all(b"Hello World!").unwrap();
res.end().unwrap();
}
fn main() {
Server::http(hello).listen("127.0.0.1:3000").unwrap();
}
And the Cargo.toml looks like this:
[package]
name = <crate_name>
version = <version>
authors = <authors>
[dependencies]
hyper = "0.3"
However, when I attempt to build it using Cargo run I get the following error:
error: invalid character `-` in crate name: `build-script-build`
error: invalid character `-` in crate name: `pkg-config`
error: invalid character `-` in crate name: `rustc-serialize`
I looked through these different crates trying to see if maybe I could just change a "rustc-serialize" to "rustc_serialize" because I think that crate names can no longer have hyphens. However, I couldn't find anything of the sort. I would really like to be able to solve this problem because I have a feeling that I am going to run into this error a few more times while Rust is still being polished.
Edit: The versions are as follows:
Rust: 1.0.0-beta.2
Hyper: 0.3.14
Cargo: 0.0.1-pre-nightly (built 2015-03-09)
Source: (StackOverflow)
I have problem with running Python hyper
library that adds support for HTTP/2
protocol.
On my Fedora machine I installed it with pip
and pip3
to use it with Python 2.7.8 and Python 3.4.1. Then I copied test script that connects with twitter:
from hyper import HTTP20Connection
conn = HTTP20Connection('twitter.com:443')
conn.request('GET', '/')
resp = conn.getresponse()
print(resp.read())
I run it using Python 2.7.8 and it ends with error:
[mn:/plib] 1 ‡ python hyper_test.py
Traceback (most recent call last):
File "hyper_test.py", line 4, in <module>
conn.request('GET', '/')
File "/usr/lib/python2.7/site-packages/hyper/http20/connection.py", line 149, in request
self.endheaders(message_body=body, final=True, stream_id=stream_id)
File "/usr/lib/python2.7/site-packages/hyper/http20/connection.py", line 310, in endheaders
self.connect()
File "/usr/lib/python2.7/site-packages/hyper/http20/connection.py", line 215, in connect
self._recv_cb()
File "/usr/lib/python2.7/site-packages/hyper/http20/connection.py", line 580, in _recv_cb
self._consume_single_frame()
File "/usr/lib/python2.7/site-packages/hyper/http20/connection.py", line 496, in _consume_single_frame
frame, length = Frame.parse_frame_header(header)
File "/usr/lib/python2.7/site-packages/hyper/http20/frame.py", line 52, in parse_frame_header
frame = FRAMES[type](stream_id)
KeyError: 80
It ends with different error with Python 3.4.1:
[mn:/plib] 1 ‡ python3 hyper_test.py
Traceback (most recent call last):
File "hyper_test.py", line 4, in <module>
conn.request('GET', '/')
File "/usr/lib/python3.4/site-packages/hyper/http20/connection.py", line 149, in request
self.endheaders(message_body=body, final=True, stream_id=stream_id)
File "/usr/lib/python3.4/site-packages/hyper/http20/connection.py", line 310, in endheaders
self.connect()
File "/usr/lib/python3.4/site-packages/hyper/http20/connection.py", line 204, in connect
sock = wrap_socket(sock, self.host)
File "/usr/lib/python3.4/site-packages/hyper/http20/tls.py", line 44, in wrap_socket
assert ssl_sock.selected_npn_protocol() in H2_NPN_PROTOCOLS
AssertionError
What can cause such problems on my environment?
Source: (StackOverflow)
The function doesn't return and hangs right before (I guess) it would drop the guard. By manually dropping the guard I can make it hang earlier. Why is this?
In the hyper code the guard of the thread pool is set in the Listener struct, but when close is called on that, nothing gets done (seemingly) with the guard of the threadpool. It just delegates to Acceptor close.
I tried dropping the mutex guard manually, but that doesn't seem to help.
I understand its expected that something active in the thread pool managed by hyper blocks further execution, but shouldn't my handler just return?
fn request_temp_code() -> TempCode {
Command::new("xdg-open").arg(format!("https://slack.com/oauth/authorize?client_id={}", SLACK_CLIENT_ID)).output().unwrap();
let server = Server::http(Ipv4Addr(127, 0, 0, 1), 9999);
let (tx, rx) = channel();
let mtx = Mutex::new(tx);
let mut guard = server.listen(move |req: Request, res: Response| {
match req.uri {
AbsolutePath(path) => {
// Trying to manually drop to see if this is the problem
let tempcode = extract_temp_code(&path).unwrap();
let gmtx = mtx.lock().unwrap();
gmtx.send(tempcode).unwrap();
drop(gmtx);
},
_ => ()
}
let mut res = res.start().unwrap();
res.write_all(b"Thanks! Please return to Lax").unwrap();
res.end().unwrap();
}).unwrap();
let tempcode = rx.recv().unwrap();
guard.close();
println!("{}", "Auth code received!");
println!("{}", "Server closed!");
// Hangs here
tempcode
}
Source: (StackOverflow)
I am trying to implement a custom HTTP header using impl_header macro from hyper crate but it seems it cannot resolve the hyper::header
module.
Here is my code:
#[macro_use] extern crate hyper;
use hyper::header;
struct CustomHeader;
impl_header!(CustomHeader, "value", String);
And here is the compiler error:
<hyper macros>:11:14: 11:20 error: unresolved import `header::HeaderFormat`. Maybe a missing `extern crate header`?
<hyper macros>:11 Result { use header:: HeaderFormat ; self . fmt_header ( f ) } } }
^~~~~~
<hyper macros>:1:1: 11:67 note: in expansion of impl_header!
lib.rs:4:1: 4:45 note: expansion site
error: aborting due to previous error
Could not compile `macro_issue`.
Any clue why this happens and how can I fix it?
Thank you
Source: (StackOverflow)
According to the documentation I could get mutable reference to the status
by calling status_mut()
. Unfortunately signature of the handler function, used to serve requests with hyper::Server contain immutable Response
, so the following code gives me an error:
pub fn handle_request(req: Request, res: Response<Fresh>){
let status: &mut StatusCode = res.status_mut();
}
error: cannot borrow immutable local variable `res` as mutable
Is there any way to set response status code in the request handler, used by hyper::server::Server?
UPD: Finally I have found the example. Right in the source code. =*)
Source: (StackOverflow)
I'm starting to get comfortable with Rust, but there are still some things that are really tripping me up with lifetimes. In this particular case, what I want to do is have an enum which may have different types wrapped as a generic parameter class to create strongly typed query parameters in a URL, though the specific use case is irrelevant, and return a conversion of that wrapped value into an &str. Here's an example of what I want to do:
enum Param<'a> {
MyBool(bool),
MyLong(i64),
MyStr(&'a str),
}
impl<'a> Param<'a> {
fn into(self) -> (&'static str, &'a str) {
match self {
Param::MyBool(b) => ("my_bool", &b.to_string()), // clearly wrong
Param::MyLong(i) => ("my_long", &i.to_string()), // clearly wrong
Param::Value(s) => ("my_str", s),
}
}
}
What I ended up doing is this to deal with the obvious lifetime issue (and yes, it's obvious to me why the lifetime isn't long enough for the into() function):
enum Param<'a> {
MyBool(&'a str), // no more static typing :(
MyLong(&'a str), // no more static typing :(
MyStr(&'a str),
}
impl<'a> Param<'a> {
fn into(self) -> (&'static str, &'a str) {
match self {
Param::MyBool(b) => ("my_bool", b),
Param::MyLong(i) => ("my_long", i),
Param::Value(s) => ("my_str", s),
}
}
}
This seems like an ugly workaround in a case where what I really want to do is guarantee the static typing of certain params, b/c now it's the constructor of the enum that's responsible for the proper type conversion. Curious if there is a way to do this... and yes, at some point I need &str as that is a parameter elsewhere, specifically:
let body = url::form_urlencoded::serialize(
vec![Param::MyBool(&true.to_string()).
into()].
into_iter());
I went through a whole bunch of things like trying to return String instead of &str
from into()
, but that only caused conversion issues down the line with a map()
of String
-> &str
. Having the tuple correct from the start is the easiest thing, rather than fighting the compiler at every turn after that.
-- update--
Ok, so I went back to a (String,String)
tuple in the into()
function for the enum. It turns out that there is an "owned" version of the url::form_urlencoded::serialize()
function which this is compatible with.
pub fn serialize_owned(pairs: &[(String, String)]) -> String
But, now I'm also trying to use the same pattern for the query string in the hyper::URL
, specifically:
fn set_query_from_pairs<'a, I>(&mut self, pairs: I)
where I: Iterator<Item=(&'a str, &'a str)>
and then I try to use map()
on the iterator that I have from the (String,String) tuple:
params: Iterator<Item=(String, String)>
url.set_query_from_pairs(params.map(|x: (String, String)| ->
(&str, &str) { let (ref k, ref v) = x; (k, v) } ));
But this gets error: x.0
does not live long enough. Ref seems correct in this case, right? If I don't use ref, then it's k/v that don't live long enough. Is there something 'simple' that I'm missing in this?
Source: (StackOverflow)