private boolean validateHeader(Fields headers, String name, String expectedValue) { Fields.Field header = headers.get(name); if (header != null && expectedValue.equals(header.value())) return true; System.out.println( name + " not valid! Expected: " + expectedValue + " headers received:" + headers); return false; }
public ByteBuffer generate(short version, Fields headers) { // TODO: ByteArrayOutputStream is quite inefficient, but grows on demand; optimize using // ByteBuffer ? final Charset iso1 = StandardCharsets.ISO_8859_1; ByteArrayOutputStream buffer = new ByteArrayOutputStream(headers.getSize() * 64); writeCount(version, buffer, headers.getSize()); for (Fields.Field header : headers) { String name = header.getName().toLowerCase(Locale.ENGLISH); byte[] nameBytes = name.getBytes(iso1); writeNameLength(version, buffer, nameBytes.length); buffer.write(nameBytes, 0, nameBytes.length); // Most common path first String value = header.getValue(); byte[] valueBytes = value.getBytes(iso1); if (header.hasMultipleValues()) { List<String> values = header.getValues(); for (int i = 1; i < values.size(); ++i) { byte[] moreValueBytes = values.get(i).getBytes(iso1); byte[] newValueBytes = new byte[valueBytes.length + 1 + moreValueBytes.length]; System.arraycopy(valueBytes, 0, newValueBytes, 0, valueBytes.length); newValueBytes[valueBytes.length] = 0; System.arraycopy( moreValueBytes, 0, newValueBytes, valueBytes.length + 1, moreValueBytes.length); valueBytes = newValueBytes; } } writeValueLength(version, buffer, valueBytes.length); buffer.write(valueBytes, 0, valueBytes.length); } return compress(version, buffer.toByteArray()); }
public boolean isUserAgentBlacklisted(Fields headers) { Fields.Field userAgentHeader = headers.get("user-agent"); if (userAgentHeader != null) for (Pattern userAgentPattern : userAgentBlacklist) if (userAgentPattern.matcher(userAgentHeader.getValue()).matches()) return true; return false; }
@Override public Set<String> apply(Stream stream, Fields requestHeaders, Fields responseHeaders) { Set<String> result = Collections.<String>emptySet(); short version = stream.getSession().getVersion(); if (!isIfModifiedSinceHeaderPresent(requestHeaders) && isValidMethod(requestHeaders.get(HTTPSPDYHeader.METHOD.name(version)).getValue()) && !isUserAgentBlacklisted(requestHeaders)) { String scheme = requestHeaders.get(HTTPSPDYHeader.SCHEME.name(version)).getValue(); String host = requestHeaders.get(HTTPSPDYHeader.HOST.name(version)).getValue(); String origin = scheme + "://" + host; String url = requestHeaders.get(HTTPSPDYHeader.URI.name(version)).getValue(); String absoluteURL = origin + url; if (LOG.isDebugEnabled()) LOG.debug("Applying push strategy for {}", absoluteURL); if (isMainResource(url, responseHeaders)) { MainResource mainResource = getOrCreateMainResource(absoluteURL); result = mainResource.getResources(); } else if (isPushResource(url, responseHeaders)) { Fields.Field referrerHeader = requestHeaders.get("referer"); if (referrerHeader != null) { String referrer = referrerHeader.getValue(); MainResource mainResource = mainResources.get(referrer); if (mainResource == null) mainResource = getOrCreateMainResource(referrer); Set<String> pushResources = mainResource.getResources(); if (!pushResources.contains(url)) mainResource.addResource(url, origin, referrer); else result = getPushResources(absoluteURL); } } if (LOG.isDebugEnabled()) LOG.debug("Pushing {} resources for {}: {}", result.size(), absoluteURL, result); } return result; }
private boolean validateUriHeader(Fields headers) { Fields.Field uriHeader = headers.get(HTTPSPDYHeader.URI.name(version)); if (uriHeader != null) if (version == SPDY.V2 && uriHeader.value().startsWith("http://")) return true; else if (version == SPDY.V3 && uriHeader.value().startsWith("/") && headers.get(HTTPSPDYHeader.HOST.name(version)) != null && headers.get(HTTPSPDYHeader.SCHEME.name(version)) != null) return true; System.out.println(HTTPSPDYHeader.URI.name(version) + " not valid!"); return false; }
private boolean isPushResource(String url, Fields responseHeaders) { for (Pattern pushRegexp : pushRegexps) { if (pushRegexp.matcher(url).matches()) { Fields.Field header = responseHeaders.get("content-type"); if (header == null) return true; String contentType = header.getValue().toLowerCase(Locale.ENGLISH); for (String pushContentType : pushContentTypes) if (contentType.startsWith(pushContentType)) return true; } } return false; }
private static ByteBuffer convertFields(String contentDisposition, Fields fields) { try { if (fields == null || fields.isEmpty()) { contentDisposition += "\r\n"; return ByteBuffer.wrap(contentDisposition.getBytes(StandardCharsets.US_ASCII)); } ByteArrayOutputStream buffer = new ByteArrayOutputStream((fields.getSize() + 1) * contentDisposition.length()); buffer.write(contentDisposition.getBytes(StandardCharsets.US_ASCII)); for (Fields.Field field : fields) { buffer.write(field.getName().getBytes(StandardCharsets.US_ASCII)); buffer.write(COLON_SPACE_BYTES); buffer.write(field.getValue().getBytes(StandardCharsets.UTF_8)); buffer.write(CR_LF_BYTES); } buffer.write(CR_LF_BYTES); return ByteBuffer.wrap(buffer.toByteArray()); } catch (IOException x) { throw new RuntimeIOException(x); } }
@Override public void onReply(Stream stream, ReplyInfo replyInfo) { HttpExchange exchange = getHttpExchange(); if (exchange == null) return; try { HttpResponse response = exchange.getResponse(); Fields fields = replyInfo.getHeaders(); short spdy = stream.getSession().getVersion(); HttpVersion version = HttpVersion.fromString(fields.get(HTTPSPDYHeader.VERSION.name(spdy)).getValue()); response.version(version); String[] status = fields.get(HTTPSPDYHeader.STATUS.name(spdy)).getValue().split(" ", 2); Integer code = Integer.parseInt(status[0]); response.status(code); String reason = status.length < 2 ? HttpStatus.getMessage(code) : status[1]; response.reason(reason); if (responseBegin(exchange)) { for (Fields.Field field : fields) { String name = field.getName(); if (HTTPSPDYHeader.from(spdy, name) != null) continue; // TODO: handle multiple values properly HttpField httpField = new HttpField(name, field.getValue()); responseHeader(exchange, httpField); } if (responseHeaders(exchange)) { if (replyInfo.isClose()) { responseSuccess(exchange); } } } } catch (Exception x) { responseFailure(x); } }
@Override public void reply(ReplyInfo replyInfo, Callback handler) { try { Fields headers = new Fields(replyInfo.getHeaders(), false); headers.remove(HTTPSPDYHeader.SCHEME.name(version)); String status = headers.remove(HTTPSPDYHeader.STATUS.name(version)).value(); Matcher matcher = statusRegexp.matcher(status); matcher.matches(); int code = Integer.parseInt(matcher.group(1)); String reason = matcher.group(2).trim(); HttpVersion httpVersion = HttpVersion.fromString(headers.remove(HTTPSPDYHeader.VERSION.name(version)).value()); // Convert the Host header from a SPDY special header to a normal header Fields.Field host = headers.remove(HTTPSPDYHeader.HOST.name(version)); if (host != null) headers.put("host", host.value()); HttpFields fields = new HttpFields(); for (Fields.Field header : headers) { String name = camelize(header.name()); fields.put(name, header.value()); } // TODO: handle better the HEAD last parameter HttpGenerator.ResponseInfo info = new HttpGenerator.ResponseInfo(httpVersion, fields, -1, code, reason, false); send(info, null, replyInfo.isClose()); if (replyInfo.isClose()) completed(); handler.succeeded(); } catch (IOException x) { handler.failed(x); } }