/** Invoked by the HTTPClient. */ public int requestHandler(Request req, Response[] resp) throws ModuleException { // parse Accept-Encoding header int idx; NVPair[] hdrs = req.getHeaders(); for (idx = 0; idx < hdrs.length; idx++) if (hdrs[idx].getName().equalsIgnoreCase("Accept-Encoding")) break; Vector pae; if (idx == hdrs.length) { hdrs = Util.resizeArray(hdrs, idx + 1); req.setHeaders(hdrs); pae = new Vector(); } else { try { pae = Util.parseHeader(hdrs[idx].getValue()); } catch (ParseException pe) { throw new ModuleException(pe.toString()); } } // done if "*;q=1.0" present HttpHeaderElement all = Util.getElement(pae, "*"); if (all != null) { NVPair[] params = all.getParams(); for (idx = 0; idx < params.length; idx++) if (params[idx].getName().equalsIgnoreCase("q")) break; if (idx == params.length) // no qvalue, i.e. q=1.0 return REQ_CONTINUE; if (params[idx].getValue() == null || params[idx].getValue().length() == 0) throw new ModuleException("Invalid q value for \"*\" in " + "Accept-Encoding header: "); try { if (Float.valueOf(params[idx].getValue()).floatValue() > 0.) return REQ_CONTINUE; } catch (NumberFormatException nfe) { throw new ModuleException( "Invalid q value for \"*\" in " + "Accept-Encoding header: " + nfe.getMessage()); } } // Add gzip, deflate and compress tokens to the Accept-Encoding header if (!pae.contains(new HttpHeaderElement("deflate"))) pae.addElement(new HttpHeaderElement("deflate")); if (!pae.contains(new HttpHeaderElement("gzip"))) pae.addElement(new HttpHeaderElement("gzip")); if (!pae.contains(new HttpHeaderElement("x-gzip"))) pae.addElement(new HttpHeaderElement("x-gzip")); if (!pae.contains(new HttpHeaderElement("compress"))) pae.addElement(new HttpHeaderElement("compress")); if (!pae.contains(new HttpHeaderElement("x-compress"))) pae.addElement(new HttpHeaderElement("x-compress")); hdrs[idx] = new NVPair("Accept-Encoding", Util.assembleHeader(pae)); return REQ_CONTINUE; }
/** * Add a token to the given header. If the header does not exist then create it with the given * token. * * @param req the request who's headers are to be modified * @param hdr the name of the header to add the token to (or to create) * @param tok the token to add * @exception ParseException if parsing the header fails */ private void addToken(Request req, String hdr, String tok) throws ParseException { int idx; NVPair[] hdrs = req.getHeaders(); for (idx = 0; idx < hdrs.length; idx++) { if (hdrs[idx].getName().equalsIgnoreCase(hdr)) break; } if (idx == hdrs.length) // no such header, so add one { hdrs = Util.resizeArray(hdrs, idx + 1); hdrs[idx] = new NVPair(hdr, tok); req.setHeaders(hdrs); } else // header exists, so add token { if (!Util.hasToken(hdrs[idx].getValue(), tok)) hdrs[idx] = new NVPair(hdr, hdrs[idx].getValue() + ", " + tok); } }
/** * Closes the stream and causes the data to be sent if it has not already been done so. This * method <strong>must</strong> be invoked when all data has been written. * * @exception IOException if any exception is thrown by the underlying socket, or if too few bytes * were written. * @exception IllegalAccessError if this stream has not been associated with a request yet. */ public synchronized void close() throws IOException, IllegalAccessError { if (req == null) throw new IllegalAccessError("Stream not associated with a request"); if (ignore) return; if (bos != null) { req.setData(bos.toByteArray()); req.setStream(null); if (trailers.length > 0) { NVPair[] hdrs = req.getHeaders(); // remove any Trailer header field int len = hdrs.length; for (int idx = 0; idx < len; idx++) { if (hdrs[idx].getName().equalsIgnoreCase("Trailer")) { System.arraycopy(hdrs, idx + 1, hdrs, idx, len - idx - 1); len--; } } // add the trailers to the headers hdrs = Util.resizeArray(hdrs, len + trailers.length); System.arraycopy(trailers, 0, hdrs, len, trailers.length); req.setHeaders(hdrs); } if (DebugConn) System.err.println("OutS: Sending request"); try { resp = req.getConnection().sendRequest(req, con_to); } catch (ModuleException me) { throw new IOException(me.toString()); } notify(); } else { if (rcvd < length) { IOException ioe = new IOException( "Premature close: only " + rcvd + " bytes written instead of the " + "expected " + length); req.getConnection().closeDemux(ioe, false); req.getConnection().outputFinished(); throw ioe; } try { if (length == -1) { if (DebugConn && trailers.length > 0) { System.err.println("OutS: Sending trailers:"); for (int idx = 0; idx < trailers.length; idx++) System.err.println( " " + trailers[idx].getName() + ": " + trailers[idx].getValue()); } os.write(Codecs.chunkedEncode(null, 0, 0, trailers, true)); } os.flush(); if (DebugConn) System.err.println("OutS: All data sent"); } catch (IOException ioe) { req.getConnection().closeDemux(ioe, true); throw ioe; } finally { req.getConnection().outputFinished(); } } }
/** Invoked by the HTTPClient. */ public int requestHandler(Request req, Response[] resp) { // First remove any Cookie headers we might have set for a previous // request NVPair[] hdrs = req.getHeaders(); int length = hdrs.length; for (int idx = 0; idx < hdrs.length; idx++) { int beg = idx; while (idx < hdrs.length && hdrs[idx].getName().equalsIgnoreCase("Cookie")) idx++; if (idx - beg > 0) { length -= idx - beg; System.arraycopy(hdrs, idx, hdrs, beg, length - beg); } } if (length < hdrs.length) { hdrs = Util.resizeArray(hdrs, length); req.setHeaders(hdrs); } // Now set any new cookie headers Hashtable cookie_list = Util.getList(cookie_cntxt_list, req.getConnection().getContext()); if (cookie_list.size() == 0) return REQ_CONTINUE; // no need to create a lot of objects Vector names = new Vector(); Vector lens = new Vector(); int version = 0; synchronized (cookie_list) { Enumeration list = cookie_list.elements(); Vector remove_list = null; while (list.hasMoreElements()) { Cookie cookie = (Cookie) list.nextElement(); if (cookie.hasExpired()) { if (LOG.isDebugEnabled()) LOG.debug("Cookie has expired and is being removed: " + cookie); if (remove_list == null) remove_list = new Vector(); remove_list.addElement(cookie); continue; } if (cookie.sendWith(req) && (cookie_handler == null || cookie_handler.sendCookie(cookie, req))) { int len = cookie.getPath().length(); int idx; // insert in correct position for (idx = 0; idx < lens.size(); idx++) if (((Integer) lens.elementAt(idx)).intValue() < len) break; names.insertElementAt(cookie.toExternalForm(), idx); lens.insertElementAt(new Integer(len), idx); if (cookie instanceof Cookie2) version = Math.max(version, ((Cookie2) cookie).getVersion()); } } // remove any marked cookies // Note: we can't do this during the enumeration! if (remove_list != null) { for (int idx = 0; idx < remove_list.size(); idx++) cookie_list.remove(remove_list.elementAt(idx)); } } if (!names.isEmpty()) { StringBuffer value = new StringBuffer(); if (version > 0) value.append("$Version=\"" + version + "\"; "); value.append((String) names.elementAt(0)); for (int idx = 1; idx < names.size(); idx++) { value.append("; "); value.append((String) names.elementAt(idx)); } hdrs = Util.resizeArray(hdrs, hdrs.length + 1); hdrs[hdrs.length - 1] = new NVPair("Cookie", value.toString()); // add Cookie2 header if necessary if (version != 1) // we currently know about version 1 only { int idx; for (idx = 0; idx < hdrs.length; idx++) if (hdrs[idx].getName().equalsIgnoreCase("Cookie2")) break; if (idx == hdrs.length) { hdrs = Util.resizeArray(hdrs, hdrs.length + 1); hdrs[hdrs.length - 1] = new NVPair("Cookie2", "$Version=\"1\""); } } req.setHeaders(hdrs); if (LOG.isDebugEnabled()) LOG.debug("Sending cookies '" + value + "'"); } return REQ_CONTINUE; }