/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.fuseki.server;
import java.text.DateFormat ;
import java.text.SimpleDateFormat ;
import java.util.Collection ;
import java.util.Date ;
import java.util.Enumeration ;
import java.util.TimeZone ;
import javax.servlet.http.HttpServletRequest ;
import javax.servlet.http.HttpServletResponse ;
import org.apache.jena.atlas.logging.Log ;
import org.apache.jena.fuseki.servlets.HttpAction ;
/** Create standard request logs (NCSA etc) */
public class RequestLog {
/*
http://httpd.apache.org/docs/current/mod/mod_log_config.html
Common Log Format (CLF)
"%h %l %u %t \"%r\" %>s %b"
Common Log Format with Virtual Host
"%v %h %l %u %t \"%r\" %>s %b"
NCSA extended/combined log format
"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
*/
/*
%l -- Identity or -
%u -- Remote user or -
%t -- Timestamp
"%r" -- Request line
%>s -- Final request status
%b -- Size in bytes
Headers.
%{}i for request header.
%{}o for response header.
*/
private static DateFormat dateFormatter ;
static {
dateFormatter = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss Z") ;
dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
}
/** NCSA combined log format *
* LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combinedfwd
* XXX.XXX.XXX.XXX - - [01/Feb/2014:03:19:09 +0000] "GET / HTTP/1.1" 200 6190 "-" "check_http/v1.4.16 (nagios-plugins 1.4.16)"
*/
public static String combinedNCSA(HttpAction action) {
HttpServletRequest request = action.request ;
HttpServletResponse response = action.response ;
return combinedNCSA(request, response) ;
}
public static String combinedNCSA(HttpServletRequest request, HttpServletResponse response) {
StringBuilder builder = new StringBuilder() ;
// Remote
String remote = get(request, "X-Forwarded-For", request.getRemoteAddr()) ;
builder.append(remote) ;
builder.append(" ") ;
// %l %u : User identity (unrelaible)
builder.append("- - ") ;
// %t
// Expensive?
builder.append("[");
// Better?
builder.append(dateFormatter.format(new Date())) ;
builder.append("] ");
// "%r"
builder.append("\"") ;
builder.append(request.getMethod()) ;
builder.append(" ") ;
// No query string - they are long and logged readably elsewhere
builder.append(request.getRequestURI()) ;
builder.append("\"") ;
//%>s -- Final request status
builder.append(" ") ;
builder.append(response.getStatus()) ;
//%b -- Size in bytes
builder.append(" ") ;
//String size = getField()
String size = get(response, "Content-Length", "-") ;
builder.append(size) ;
// "%{Referer}i"
builder.append(" \"") ;
builder.append(get(request, "Referer", "")) ;
builder.append("\"") ;
// "%{User-Agent}i"
builder.append(" \"") ;
builder.append(get(request, "User-Agent", "")) ;
builder.append("\"") ;
return builder.toString() ;
}
private static String get(HttpServletRequest request, String name, String dft) {
String x = get(request, name) ;
if ( x == null )
x = dft ;
return x ;
}
private static String get(HttpServletRequest request, String name) {
Enumeration<String> en = request.getHeaders(name) ;
if ( ! en.hasMoreElements() ) return null ;
String x = en.nextElement() ;
if ( en.hasMoreElements() ) {
Log.warn(RequestLog.class, "Multiple request header values") ;
}
return x ;
}
private static String get(HttpServletResponse response, String name, String dft) {
String x = get(response, name) ;
if ( x == null )
x = dft ;
return x ;
}
private static String get(HttpServletResponse response, String name) {
Collection<String> en = response.getHeaders(name) ;
if ( en.isEmpty() )return null ;
if ( en.size() != 1 ) Log.warn(RequestLog.class, "Multiple response header values") ;
return response.getHeader(name) ;
}
}