Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

How to use mango HttpProvider

Moderators: larsivi kris

Posted: 11/27/08 05:49:11 Modified: 11/27/08 05:56:29

I try write a HttpProxy? server use mango and tango, Code has been unable to correct the remore server data copy.

I write a ticket in there http://www.dsource.org/projects/mango/ticket/37.

private{
	import 
	
		tango.util.log.Trace,
		
		tango.io.Buffer,
		tango.io.File,
		tango.io.Console,
		tango.io.device.NullConduit,
		
		tango.util.log.Log,
		tango.util.log.Trace,
		tango.util.log.Config,
	
		tango.time.Clock,
	
		
		tango.net.Socket,
		tango.net.SocketConduit,
                tango.net.InternetAddress,
		tango.net.http.HttpConst,
		tango.net.http.HttpClient,
		tango.net.http.HttpGet,
		tango.net.http.HttpHeaders,
		tango.net.http.model.HttpParamsView,	
		tango.net.http.HttpParams,
		tango.net.http.HttpCookies,
		tango.net.http.HttpTriplet,
		
		tango.stdc.stringz,
		
		tango.text.stream.LineIterator,		
		tango.text.json.Json,
		tango.text.convert.Layout,
		tango.text.Util,
		tango.text.Regex,
		tango.util.Convert;
	
	import 
		mango.net.http.server.HttpServer,
		mango.net.http.server.HttpRequest,
		mango.net.http.server.HttpResponse,
		mango.net.http.server.HttpProvider ;
}

class ProxyProvider : HttpProvider {
	private{
		SocketConduit	socket;
		HttpHeaders		headersOut;
		HttpHeaders		headersIn;
        	HttpParams		paramsOut;
        	IBuffer			tmp,
                                        input,
                                        output;
		Uri			_uri;
		char[]			_url,
					_host;
		ResponseLine		responseLine;
		LineIterator!(char)	line;
	}
	
	
	override void service (HttpRequest req, HttpResponse res){
		
		//replace the _url to proxy object url
		_url		= "http://www.google.com"; 
		
		_uri		= new Uri(_url);	
		output		= new Buffer(1024 * 4);
		input		= new Buffer(1024 * 4);
		tmp		= new Buffer(1024 * 4);		
		responseLine	= new ResponseLine;
		
		
		headersOut	= new HttpHeaders (new Buffer (1024 * 4));
		headersIn	= new HttpHeaders (new Buffer (1024 * 4));
		paramsOut	= new HttpParams  (new Buffer (1024 * 4));
		
		_host		= _uri.getHost;
		if( _host is null){
			responseLine.error ("host error");
			return ;
		}
		
		socket		= new SocketConduit();		
		auto addr 	= new InternetAddress (_host, _uri.getValidPort);	
		socket.connect(addr);
		CopyHeader(req, res);
		
		
		// tmp.slice is the "Client Response Headers";
		Trace.formatln("=====\n{}\n======", cast(char[])tmp.slice).flush;
		// How to send it to Client ???			
		// The following lines Code Seems to working
		auto ClientOutputHeader		= res.getOutputHeaders();
		ClientOutputHeader.parse(tmp);
		res.keepAlive(true);
		
		// how to copy the Remote Context to Clint ???
		// The following lines Code Output wrong HttpResponse 
		// the Client HttpResponse headers Sent 2 times
		// the Client HttpResponse Context is more than sended.
		// some strange stuff following the designated context.
		auto ClientOutBuffer	= res.getOutputBuffer();
		ClientOutBuffer.append("123").flush;

	}
	
	
	
	void CopyHeader(ref HttpRequest req,  ref HttpResponse res){
		auto query			= _uri.extendQuery(paramsOut.formatTokens(tmp, "&"));
                auto path			= _uri.getPath;
                if (path.length is 0)	path	= "/";		
		headersOut.add(HttpHeader.Host, _uri.getHost);
		
		auto ClientInputHeader		= req.getInputHeaders();
		
		Trace.formatln("copy Client Request to Remote Request").flush;
		foreach(ref c; ClientInputHeader){
			if( 
				c.name.value	!= HttpHeader.Host.value &&
				c.name.value	!= HttpHeader.Cookie.value &&
				c.name.value	!= HttpHeader.Referrer.value
				
			)
			headersOut.add(c.name, c.value);		
		}
		
		output("GET ")(path)( query.length ? "?" : "" )(query)(" ")("HTTP/1.1")(HttpConst.Eol);
		headersOut.produce (&output.consume, HttpConst.Eol);
		
		
		Trace.formatln("commit Remote Request").flush;
		output(HttpConst.Eol).output(socket).flush;
		Trace.formatln("{}", cast(char[])output.slice).flush;

		Trace.formatln("Read Remote Response status").flush;
		input.input(socket);		
		line		= new LineIterator!(char)(input);
		while (line.next && line.get.length is 0){}
		
		if (socket.hadTimeout) responseLine.error ("response timeout");
		if (line.get.length is 0) responseLine.error ("truncated response");
		responseLine.parse (line.get);
		switch (responseLine.getStatus){
			case HttpResponseCode.Found:
			case HttpResponseCode.SeeOther:
			case HttpResponseCode.MovedPermanently:
			case HttpResponseCode.TemporaryRedirect:
                                close;
				responseLine.error ("Status: " ~ to!(char[])(responseLine.getStatus));
			default:
                               break;
		}
		Trace.formatln("Read Remote Response Headers").flush;
		headersIn.reset.parse (input);
		
		
		Trace.formatln("copy Read Remote Response Headers to client").flush;	
		tmp.clear;
		//tmp(`HTTP/1.1 200 OK`)(HttpConst.Eol);
		foreach(ref c; headersIn){
			tmp(c.name.value)(c.value)(HttpConst.Eol);
		}
		tmp(HttpConst.Eol);
	}

	
	void close(){
		if (socket){
			socket.shutdown(); //SocketShutdown.BOTH
			socket.detach;
			socket = null;
		}
	}
	
}

pragma(lib, "mango.lib");

void main(){
	Trace.formatln("http://127.0.0.1:8000/" ).flush;
	auto addr = new InternetAddress (8000);
        auto server = new HttpServer (new ProxyProvider, addr, 10, 100);
        server.start;
}

Any concerns will be appreciated.

There are no responses to display.