- From: Anselm Baird_Smith <abaird@www43.inria.fr>
- Date: Tue, 19 Nov 1996 09:37:37 +0100 (MET)
- To: Gordon Dakin <gad@hunchuen.crystaliz.com>
- Cc: www-jigsaw@w3.org
Gordon Dakin writes: > > > Thanks for your help so far. > > I'm still having some trouble doings proxied PUTs. As I described in an > earlier message, I incorporated ForwardRequest's attributes and methods > (like dupReqest) into my own class, which extends FileResource, and I'm > trying to do a PUT to a remote machine also running Jigsaw. So far, > proxied GETs work, but proxied PUTs yield a message "Request doesn't have > a valid context", because request.getInputStream() returns null at the > remote jigsaw. Could you provide more infos ? I can't remember, but check that enclosed version of w3c.jigsaw.http.Request is the one you use (and let me know if it differs) > I've tried to set the request's input stream to an arbitrary stream in > the host jigsaw, by modifying dupRequest() -- I replaced > req.setOutputStream(getInputStream()) with > req.setOutputStream(myOwnStream), but on the client machine. > request.getInputStream() returns null in FileResource.put(). This experiment should work, didi you set the conmtent length appropriately. Anselm. // Request.java // $Id: Request.java,v 1.17 1996/11/08 14:56:49 abaird Exp $ // (c) COPYRIGHT MIT and INRIA, 1996. // Please first read the full copyright statement in file COPYRIGHT.html package w3c.jigsaw.http ; import java.io.*; import java.util.*; import java.net.*; import w3c.www.mime.* ; import w3c.www.http.* ; import w3c.util.*; import w3c.jigsaw.resources.*; /** * this class extends HttpRequestMessage to cope with HTTP request. * One subtely here: note how each field acessor <em>never</em> throws an * exception, but rather is provided with a default value: this is in the hope * that sometime, HTTP will not require all the parsing it requires right now. */ public class Request extends HttpRequestMessage implements HTTP { /** * The URL that means <strong>*</strong> for an <code>OPTIONS</code> * method. */ public static URL THE_SERVER = null; static { try { THE_SERVER = new URL("http://your.url.unknown"); } catch (Exception ex) { ex.printStackTrace(); } } protected Client client = null; protected MimeParser parser = null; protected InputStream in = null; protected boolean keepcon = true; boolean is_proxy = false; /** * Fix the target URL of the request, this is the only good time to do so. */ public void notifyEndParsing(MimeParser parser) throws HttpParserException, IOException { super.notifyEndParsing(parser); String target = getTarget(); String url = null; // Get rid of the nasty cases (who deserve a place in hell ?) if ( target.equals("*") ) { setURL(THE_SERVER); return; } // Is this a full http URL: int colon = target.indexOf(':'); if ((colon != -1) && target.substring(0, colon).equals("http")) { // Good we have a full URL: url = target; } else { // Do we have a valid host header ? String host = getHost(); if ( host == null ) url = getClient().getServer().getURL() + target; else url = "http://" + host + target; } // Now parse the URL: try { setURL(new URL(url)); } catch (Exception ex) { throw new HttpParserException("Invalid URL ["+url+"]"); } // not reached ! } // FIXME // This guy should also check that the (optional) request stream has been // exhausted. public boolean canKeepConnection() { // HTTP/0.9 doesn't know about keeping connections alive: if (( ! keepcon) || (major < 1)) return false; if ( minor >= 1 ) // HTTP/1.1 keeps connections alive by default return hasConnection("close") ? false : true; // For HTTP/1.0 check the [proxy] connection header: if ( is_proxy ) return hasProxyConnection("keep-alive"); else return hasConnection("keep-alive"); } private HTTPResource target_resource = null; protected void setTargetResource(HTTPResource resource) { target_resource = resource; } /** * Get this request target resource. * @return An instance of HTTPResource, or <strong>null</strong> if * not found. */ public HTTPResource getTargetResource() { return target_resource; } public void setProxy(boolean onoff) { is_proxy = onoff; } public boolean isProxy() { return is_proxy; } public String getURLPath() { return url.getFile(); } public void setURLPath(String path) { try { url = new URL(url, path); } catch (Exception ex) { ex.printStackTrace(); } } public boolean hasContentLength() { return hasHeader(H_CONTENT_LENGTH); } public boolean hasContentType() { return hasHeader(H_CONTENT_TYPE); } public boolean hasAccept() { return hasHeader(H_ACCEPT); } public boolean hasAcceptEncoding() { return hasHeader(H_ACCEPT_ENCODING); } public boolean hasAcceptLanguage() { return hasHeader(H_ACCEPT_LANGUAGE); } public boolean hasAuthorization() { return hasHeader(H_AUTHORIZATION); } public boolean hasProxyAuthorization() { return hasHeader(H_PROXY_AUTHORIZATION); } public String getQueryString() { return (String) getState("query"); } public boolean hasQueryString() { return hasState("query"); } protected boolean internal = false; public boolean isInternal() { return internal; } public void setInternal(boolean onoff) { this.internal = onoff; } protected Request original = null; public Request getOriginal() { return original == null ? this : original ; } /** * Clone this request, in order to launch an internal request. * This method can be used to run a request in some given context, defined * by an original request. It will preserve all the original information * (such as authentication, etc), and will provide a <em>clone</em> of * the original request. * <p>The original request and its clone differ in the following way: * <ul> * <li>The clone is marked as <em>internal</em>, which can be tested * by the <code>isInternal</code> method. * <li>The clone will keep a pointer to the first request that was * cloned. This original request can be accessed by the <code>getOriginal * </code> method. * </ul> * <p>To run an internal request, the caller can then use the <code> * w3c.jigsaw.http.httpd</code> <code>perform</code> method. * @return A fresh Request instance, marked as internal. */ public HttpMessage getClone() { Request cl = (Request) super.getClone(); cl.internal = true; if ( cl.original == null ) cl.original = this; return cl; } /** * Get this reply entity body. * The reply entity body is returned as an InputStream, that the caller * has to read to actually get the bytes of the content. * @return An InputStream instance. If the reply has no body, the returned * input stream will just return <strong>-1</strong> on first read. */ public InputStream getInputStream() throws IOException { if ( in != null ) return in; // Find out which method is used to the length: int len = getContentLength(); if ( len >= 0 ) { in = new ContentLengthInputStream(parser.getInputStream(), len); } else { // No content length, try out chunked encoding: String te[] = getTransferEncoding() ; if ( te != null ) { for (int i = 0 ; i < te.length ; i++) { if (te[i].equals("chunked")) in = new ChunkedInputStream(parser.getInputStream()); } } } // Handle broken HTTP/1.0 request // It is mandatory for 1.1 requests to have been handled above. if ((major == 1) && (minor == 0) && (in == null)) { String m = getMethod(); if (m.equals("POST") || m.equals("PUT")) { keepcon = false; in = parser.getInputStream(); } } return in; } /** * Unescape a HTTP escaped string * @param s The string to be unescaped * @return the unescaped string. */ public static String unescape (String s) { StringBuffer sbuf = new StringBuffer () ; int l = s.length() ; int ch = -1 ; for (int i = 0 ; i < l ; i++) { switch (ch = s.charAt(i)) { case '%': ch = s.charAt (++i) ; int hb = (Character.isDigit ((char) ch) ? ch - '0' : Character.toLowerCase ((char) ch) - 'a') & 0xF ; ch = s.charAt (++i) ; int lb = (Character.isDigit ((char) ch) ? ch - '0' : Character.toLowerCase ((char) ch) - 'a') & 0xF ; sbuf.append ((char) ((hb << 4) | lb)) ; break ; case '+': sbuf.append (' ') ; break ; default: sbuf.append ((char) ch) ; } } return sbuf.toString() ; } /** * Make an empty Reply object matching this request version. * @param status The status of the reply. */ public Reply makeReply(int status) { return new Reply(client, getMajorVersion(), getMinorVersion(), status); } /** * Get the client of this request. */ public Client getClient() { return client ; } public Request (Client client, MimeParser parser) { super (parser); this.parser = parser; this.client = client ; } }
Received on Tuesday, 19 November 1996 03:37:57 UTC