@Override public void setCharacterEncoding(String encoding) { if (isIncluding()) return; if (_outputType == OutputType.NONE && !isCommitted()) { if (encoding == null) { // Clear any encoding. if (_characterEncoding != null) { _characterEncoding = null; if (_contentType != null) { _contentType = MimeTypes.getContentTypeWithoutCharset(_contentType); HttpField field = HttpField.CONTENT_TYPE.get(_contentType); if (field != null) _fields.put(field); else _fields.put(HttpHeader.CONTENT_TYPE, _contentType); } } } else { // No, so just add this one to the mimetype _characterEncoding = StringUtil.normalizeCharset(encoding); if (_contentType != null) { _contentType = MimeTypes.getContentTypeWithoutCharset(_contentType) + ";charset=" + _characterEncoding; HttpField field = HttpField.CONTENT_TYPE.get(_contentType); if (field != null) _fields.put(field); else _fields.put(HttpHeader.CONTENT_TYPE, _contentType); } } } }
/* ------------------------------------------------------------ */ private HttpContent load(String pathInContext, Resource resource) throws IOException { Content content = null; if (resource == null || !resource.exists()) return null; // Will it fit in the cache? if (!resource.isDirectory() && isCacheable(resource)) { // Create the Content (to increment the cache sizes before adding the content content = new Content(pathInContext, resource); // reduce the cache to an acceptable size. shrinkCache(); // Add it to the cache. Content added = _cache.putIfAbsent(pathInContext, content); if (added != null) { content.invalidate(); content = added; } return content; } return new HttpContent.ResourceAsHttpContent( resource, _mimeTypes.getMimeByExtension(resource.toString()), getMaxCachedFileSize(), _etags); }
@Override public PrintWriter getWriter() throws IOException { if (_outputType == OutputType.STREAM) throw new IllegalStateException("STREAM"); if (_outputType == OutputType.NONE) { /* get encoding from Content-Type header */ String encoding = _characterEncoding; if (encoding == null) { encoding = MimeTypes.inferCharsetFromContentType(_contentType); if (encoding == null) encoding = StringUtil.__ISO_8859_1; setCharacterEncoding(encoding); } if (_writer != null && _writer.isFor(encoding)) _writer.reopen(); else { if (StringUtil.__ISO_8859_1.equalsIgnoreCase(encoding)) _writer = new ResponseWriter(new Iso88591HttpWriter(_out), encoding); else if (StringUtil.__UTF8.equalsIgnoreCase(encoding)) _writer = new ResponseWriter(new Utf8HttpWriter(_out), encoding); else _writer = new ResponseWriter(new EncodingHttpWriter(_out, encoding), encoding); } // Set the output type at the end, because setCharacterEncoding() checks for it _outputType = OutputType.WRITER; } return _writer; }
@Override public boolean parsedHeader(HttpField field) { HttpHeader header = field.getHeader(); String value = field.getValue(); if (value == null) value = ""; if (header != null) { switch (header) { case EXPECT: if (_version.getVersion() >= HttpVersion.HTTP_1_1.getVersion()) { HttpHeaderValue expect = HttpHeaderValue.CACHE.get(value); switch (expect == null ? HttpHeaderValue.UNKNOWN : expect) { case CONTINUE: _expect100Continue = true; break; case PROCESSING: _expect102Processing = true; break; default: String[] values = value.split(","); for (int i = 0; values != null && i < values.length; i++) { expect = HttpHeaderValue.CACHE.get(values[i].trim()); if (expect == null) _expect = true; else { switch (expect) { case CONTINUE: _expect100Continue = true; break; case PROCESSING: _expect102Processing = true; break; default: _expect = true; } } } } } break; case CONTENT_TYPE: MimeTypes.Type mime = MimeTypes.CACHE.get(value); String charset = (mime == null || mime.getCharset() == null) ? MimeTypes.getCharsetFromContentType(value) : mime.getCharset().toString(); if (charset != null) _request.setCharacterEncodingUnchecked(charset); break; default: } } if (field.getName() != null) _request.getHttpFields().add(field); return false; }
@Override public void setContentType(String contentType) { if (isCommitted() || isIncluding()) return; if (contentType == null) { if (isWriting() && _characterEncoding != null) throw new IllegalSelectorException(); if (_locale == null) _characterEncoding = null; _mimeType = null; _contentType = null; _fields.remove(HttpHeader.CONTENT_TYPE); } else { _contentType = contentType; _mimeType = MimeTypes.CACHE.get(contentType); String charset; if (_mimeType != null && _mimeType.getCharset() != null) charset = _mimeType.getCharset().toString(); else charset = MimeTypes.getCharsetFromContentType(contentType); if (charset == null) { if (_characterEncoding != null) { _contentType = contentType + ";charset=" + _characterEncoding; _mimeType = null; } } else if (isWriting() && !charset.equals(_characterEncoding)) { // too late to change the character encoding; _mimeType = null; _contentType = MimeTypes.getContentTypeWithoutCharset(_contentType); if (_characterEncoding != null) _contentType = _contentType + ";charset=" + _characterEncoding; } else { _characterEncoding = charset; } HttpField field = HttpField.CONTENT_TYPE.get(_contentType); if (field != null) _fields.put(field); else _fields.put(HttpHeader.CONTENT_TYPE, _contentType); } }
/* ------------------------------------------------------------ */ CachedHttpContent(String pathInContext, Resource resource, CachedHttpContent gzipped) { _key = pathInContext; _resource = resource; String contentType = _mimeTypes.getMimeByExtension(_resource.toString()); _contentType = contentType == null ? null : new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, contentType); _characterEncoding = _contentType == null ? null : MimeTypes.getCharsetFromContentType(contentType); _mimeType = _contentType == null ? null : MimeTypes.CACHE.get(MimeTypes.getContentTypeWithoutCharset(contentType)); boolean exists = resource.exists(); _lastModifiedValue = exists ? resource.lastModified() : -1L; _lastModified = _lastModifiedValue == -1 ? null : new PreEncodedHttpField( HttpHeader.LAST_MODIFIED, DateGenerator.formatDate(_lastModifiedValue)); _contentLengthValue = exists ? (int) resource.length() : 0; _contentLength = new PreEncodedHttpField(HttpHeader.CONTENT_LENGTH, Long.toString(_contentLengthValue)); if (_cachedFiles.incrementAndGet() > _maxCachedFiles) shrinkCache(); _lastAccessed = System.currentTimeMillis(); _etag = ResourceCache.this._etags ? new PreEncodedHttpField(HttpHeader.ETAG, resource.getWeakETag()) : null; _gzipped = gzipped == null ? null : new CachedGzipHttpContent(this, gzipped); }
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String fileName = request.getServletPath(); byte[] dataBytes = loadContentFileBytes(fileName); response.setContentLength(dataBytes.length); if (fileName.endsWith(".js")) { // intentionally long-form content type to test ";" splitting in code response.setContentType("text/javascript; charset=utf-8"); } else { String mime = mimeTypes.getMimeByExtension(fileName); if (mime != null) response.setContentType(mime); } ServletOutputStream out = response.getOutputStream(); out.write(dataBytes); }
/* * @see org.eclipse.jetty.server.server.HttpParser.EventHandler#parsedHeaderValue(org.eclipse.io.Buffer) */ @Override public void parsedHeader(Buffer name, Buffer value) { int ho = HttpHeaders.CACHE.getOrdinal(name); switch (ho) { case HttpHeaders.HOST_ORDINAL: // TODO check if host matched a host in the URI. _host = true; break; case HttpHeaders.EXPECT_ORDINAL: value = HttpHeaderValues.CACHE.lookup(value); switch (HttpHeaderValues.CACHE.getOrdinal(value)) { case HttpHeaderValues.CONTINUE_ORDINAL: _expect100Continue = _generator instanceof HttpGenerator; break; case HttpHeaderValues.PROCESSING_ORDINAL: _expect102Processing = _generator instanceof HttpGenerator; break; default: String[] values = value.toString().split(","); for (int i = 0; values != null && i < values.length; i++) { CachedBuffer cb = HttpHeaderValues.CACHE.get(values[i].trim()); if (cb == null) _expect = true; else { switch (cb.getOrdinal()) { case HttpHeaderValues.CONTINUE_ORDINAL: _expect100Continue = _generator instanceof HttpGenerator; break; case HttpHeaderValues.PROCESSING_ORDINAL: _expect102Processing = _generator instanceof HttpGenerator; break; default: _expect = true; } } } } break; case HttpHeaders.ACCEPT_ENCODING_ORDINAL: case HttpHeaders.USER_AGENT_ORDINAL: value = HttpHeaderValues.CACHE.lookup(value); break; case HttpHeaders.CONTENT_TYPE_ORDINAL: value = MimeTypes.CACHE.lookup(value); _charset = MimeTypes.getCharsetFromContentType(value); break; case HttpHeaders.CONNECTION_ORDINAL: // looks rather clumsy, but the idea is to optimize for a single valued header switch (HttpHeaderValues.CACHE.getOrdinal(value)) { case -1: { String[] values = value.toString().split(","); for (int i = 0; values != null && i < values.length; i++) { CachedBuffer cb = HttpHeaderValues.CACHE.get(values[i].trim()); if (cb != null) { switch (cb.getOrdinal()) { case HttpHeaderValues.CLOSE_ORDINAL: _responseFields.add( HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE_BUFFER); _generator.setPersistent(false); break; case HttpHeaderValues.KEEP_ALIVE_ORDINAL: if (_version == HttpVersions.HTTP_1_0_ORDINAL) _responseFields.add( HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.KEEP_ALIVE_BUFFER); break; } } } break; } case HttpHeaderValues.CLOSE_ORDINAL: _responseFields.put(HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE_BUFFER); _generator.setPersistent(false); break; case HttpHeaderValues.KEEP_ALIVE_ORDINAL: if (_version == HttpVersions.HTTP_1_0_ORDINAL) _responseFields.put( HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.KEEP_ALIVE_BUFFER); break; } } _requestFields.add(name, value); }
protected void commit(ByteBuffer content, boolean complete, Callback callback) { // Are we excluding because of status? Response response = _channel.getResponse(); int sc = response.getStatus(); if (sc > 0 && (sc < 200 || sc == 204 || sc == 205 || sc >= 300)) { LOG.debug("{} exclude by status {}", this, sc); noCompression(); if (sc == 304) { String request_etags = (String) _channel.getRequest().getAttribute("o.e.j.s.h.gzip.GzipHandler.etag"); String response_etag = response.getHttpFields().get(HttpHeader.ETAG); if (request_etags != null && response_etag != null) { String response_etag_gzip = etagGzip(response_etag); if (request_etags.contains(response_etag_gzip)) response.getHttpFields().put(HttpHeader.ETAG, response_etag_gzip); } } _interceptor.write(content, complete, callback); return; } // Are we excluding because of mime-type? String ct = response.getContentType(); if (ct != null) { ct = MimeTypes.getContentTypeWithoutCharset(ct); if (!_factory.isMimeTypeGzipable(StringUtil.asciiToLowerCase(ct))) { LOG.debug("{} exclude by mimeType {}", this, ct); noCompression(); _interceptor.write(content, complete, callback); return; } } // Has the Content-Encoding header already been set? HttpFields fields = response.getHttpFields(); String ce = fields.get(HttpHeader.CONTENT_ENCODING); if (ce != null) { LOG.debug("{} exclude by content-encoding {}", this, ce); noCompression(); _interceptor.write(content, complete, callback); return; } // Are we the thread that commits? if (_state.compareAndSet(GZState.MIGHT_COMPRESS, GZState.COMMITTING)) { // We are varying the response due to accept encoding header. if (_vary != null) { if (fields.contains(HttpHeader.VARY)) fields.addCSV(HttpHeader.VARY, _vary.getValues()); else fields.add(_vary); } long content_length = response.getContentLength(); if (content_length < 0 && complete) content_length = content.remaining(); _deflater = _factory.getDeflater(_channel.getRequest(), content_length); if (_deflater == null) { LOG.debug("{} exclude no deflater", this); _state.set(GZState.NOT_COMPRESSING); _interceptor.write(content, complete, callback); return; } fields.put(GZIP._contentEncoding); _crc.reset(); _buffer = _channel.getByteBufferPool().acquire(_bufferSize, false); BufferUtil.fill(_buffer, GZIP_HEADER, 0, GZIP_HEADER.length); // Adjust headers response.setContentLength(-1); String etag = fields.get(HttpHeader.ETAG); if (etag != null) fields.put(HttpHeader.ETAG, etagGzip(etag)); LOG.debug("{} compressing {}", this, _deflater); _state.set(GZState.COMPRESSING); gzip(content, complete, callback); } else callback.failed(new WritePendingException()); }
/* ------------------------------------------------------------ */ private HttpContent load(String pathInContext, Resource resource, int maxBufferSize) throws IOException { if (resource == null || !resource.exists()) return null; if (resource.isDirectory()) return new ResourceHttpContent( resource, _mimeTypes.getMimeByExtension(resource.toString()), getMaxCachedFileSize()); // Will it fit in the cache? if (isCacheable(resource)) { CachedHttpContent content = null; // Look for a gzip resource if (_gzip) { String pathInContextGz = pathInContext + ".gz"; CachedHttpContent contentGz = _cache.get(pathInContextGz); if (contentGz == null || !contentGz.isValid()) { contentGz = null; Resource resourceGz = _factory.getResource(pathInContextGz); if (resourceGz.exists() && resourceGz.lastModified() >= resource.lastModified() && resourceGz.length() < resource.length()) { contentGz = new CachedHttpContent(pathInContextGz, resourceGz, null); CachedHttpContent added = _cache.putIfAbsent(pathInContextGz, contentGz); if (added != null) { contentGz.invalidate(); contentGz = added; } } } content = new CachedHttpContent(pathInContext, resource, contentGz); } else content = new CachedHttpContent(pathInContext, resource, null); // Add it to the cache. CachedHttpContent added = _cache.putIfAbsent(pathInContext, content); if (added != null) { content.invalidate(); content = added; } return content; } // Look for non Cacheable gzip resource or content String mt = _mimeTypes.getMimeByExtension(pathInContext); if (_gzip) { // Is the gzip content cached? String pathInContextGz = pathInContext + ".gz"; CachedHttpContent contentGz = _cache.get(pathInContextGz); if (contentGz != null && contentGz.isValid() && contentGz.getResource().lastModified() >= resource.lastModified()) return new ResourceHttpContent(resource, mt, maxBufferSize, contentGz); // Is there a gzip resource? Resource resourceGz = _factory.getResource(pathInContextGz); if (resourceGz.exists() && resourceGz.lastModified() >= resource.lastModified() && resourceGz.length() < resource.length()) return new ResourceHttpContent( resource, mt, maxBufferSize, new ResourceHttpContent( resourceGz, _mimeTypes.getMimeByExtension(pathInContextGz), maxBufferSize)); } return new ResourceHttpContent(resource, mt, maxBufferSize); }