View | Details | Raw Unified | Return to bug 52674
Collapse All | Expand All

(-)src/protocol/http/org/apache/jmeter/protocol/http/proxy/DefaultSamplerCreator.java (+231 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *   http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
19
package org.apache.jmeter.protocol.http.proxy;
20
21
import java.io.File;
22
import java.io.IOException;
23
import java.net.URL;
24
import java.util.Map;
25
26
import org.apache.commons.io.FileUtils;
27
import org.apache.jmeter.protocol.http.config.MultipartUrlConfig;
28
import org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui;
29
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
30
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerFactory;
31
import org.apache.jmeter.protocol.http.sampler.PostWriter;
32
import org.apache.jmeter.protocol.http.util.ConversionUtils;
33
import org.apache.jmeter.protocol.http.util.HTTPConstants;
34
import org.apache.jmeter.protocol.http.util.HTTPFileArg;
35
import org.apache.jmeter.testelement.TestElement;
36
import org.apache.jorphan.logging.LoggingManager;
37
import org.apache.log.Logger;
38
39
/**
40
 * 
41
 */
42
public class DefaultSamplerCreator extends AbstractSamplerCreator {
43
    private static final Logger log = LoggingManager.getLoggerForClass();
44
 
45
    /**
46
     * 
47
     */
48
    public DefaultSamplerCreator() {
49
    }
50
51
    /**
52
     * @see org.apache.jmeter.protocol.http.proxy.SamplerCreator#getManagedContentTypes()
53
     */
54
    public String[] getManagedContentTypes() {
55
        return new String[0];
56
    }
57
58
    /* (non-Javadoc)
59
     * @see org.apache.jmeter.protocol.http.proxy.SamplerCreator#createSampler(org.apache.jmeter.protocol.http.proxy.HttpRequestHdr, java.util.Map, java.util.Map)
60
     */
61
    public HTTPSamplerBase createSampler(HttpRequestHdr request,
62
            Map<String, String> pageEncodings, Map<String, String> formEncodings) {
63
        // Instantiate the sampler
64
        HTTPSamplerBase sampler = HTTPSamplerFactory.newInstance(request.getHttpSamplerName());
65
        // Damn! A whole new GUI just to instantiate a test element?
66
        // Isn't there a beter way?
67
        HttpTestSampleGui tempGui = new HttpTestSampleGui();
68
69
        sampler.setProperty(TestElement.GUI_CLASS, tempGui.getClass().getName());
70
71
        tempGui.configure(sampler);
72
        tempGui.modifyTestElement(sampler);
73
        // Defaults
74
        sampler.setFollowRedirects(false);
75
        sampler.setUseKeepAlive(true);
76
77
        if (log.isDebugEnabled()) {
78
            log.debug("getSampler: sampler path = " + sampler.getPath());
79
        }
80
        return sampler;
81
    }
82
83
    /* (non-Javadoc)
84
     * @see org.apache.jmeter.protocol.http.proxy.SamplerCreator#populateSampler(org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase, org.apache.jmeter.protocol.http.proxy.HttpRequestHdr, java.util.Map, java.util.Map)
85
     */
86
    public void populateSampler(HTTPSamplerBase sampler,
87
            HttpRequestHdr request, Map<String, String> pageEncodings,
88
            Map<String, String> formEncodings) throws Exception{
89
        sampler.setDomain(request.serverName());
90
        if (log.isDebugEnabled()) {
91
            log.debug("Proxy: setting server: " + sampler.getDomain());
92
        }
93
        sampler.setMethod(request.getMethod());
94
        log.debug("Proxy: setting method: " + sampler.getMethod());
95
        sampler.setPort(request.serverPort());
96
        if (log.isDebugEnabled()) {
97
            log.debug("Proxy: setting port: " + sampler.getPort());
98
        }
99
        sampler.setProtocol(request.getProtocol(sampler));
100
101
        URL pageUrl = null;
102
        if(sampler.isProtocolDefaultPort()) {
103
            pageUrl = new URL(sampler.getProtocol(), sampler.getDomain(), request.getPath());
104
        }
105
        else {
106
            pageUrl = new URL(sampler.getProtocol(), sampler.getDomain(), 
107
                    sampler.getPort(), request.getPath());
108
        }
109
        String urlWithoutQuery = request.getUrlWithoutQuery(pageUrl);
110
111
112
        // Check if the request itself tells us what the encoding is
113
        String contentEncoding = null;
114
        String requestContentEncoding = ConversionUtils.getEncodingFromContentType(
115
                request.getContentType());
116
        if(requestContentEncoding != null) {
117
            contentEncoding = requestContentEncoding;
118
        }
119
        else {
120
            // Check if we know the encoding of the page
121
            if (pageEncodings != null) {
122
                synchronized (pageEncodings) {
123
                    contentEncoding = pageEncodings.get(urlWithoutQuery);
124
                }
125
            }
126
            // Check if we know the encoding of the form
127
            if (formEncodings != null) {
128
                synchronized (formEncodings) {
129
                    String formEncoding = formEncodings.get(urlWithoutQuery);
130
                    // Form encoding has priority over page encoding
131
                    if (formEncoding != null) {
132
                        contentEncoding = formEncoding;
133
                    }
134
                }
135
            }
136
        }
137
138
        // Get the post data using the content encoding of the request
139
        String postData = null;
140
        if (log.isDebugEnabled()) {
141
            if(contentEncoding != null) {
142
                log.debug("Using encoding " + contentEncoding + " for request body");
143
            }
144
            else {
145
                log.debug("No encoding found, using JRE default encoding for request body");
146
            }
147
        }
148
        if (contentEncoding != null) {
149
            postData = new String(request.getRawPostData(), contentEncoding);
150
        } else {
151
            // Use default encoding
152
            postData = new String(request.getRawPostData(), PostWriter.ENCODING);
153
        }
154
155
        if(contentEncoding != null) {
156
            sampler.setPath(request.getPath(), contentEncoding);
157
        }
158
        else {
159
            // Although the spec says UTF-8 should be used for encoding URL parameters,
160
            // most browser use ISO-8859-1 for default if encoding is not known.
161
            // We use null for contentEncoding, then the url parameters will be added
162
            // with the value in the URL, and the "encode?" flag set to false
163
            sampler.setPath(request.getPath(), null);
164
        }
165
        if (log.isDebugEnabled()) {
166
            log.debug("Proxy: setting path: " + sampler.getPath());
167
        }
168
        if (!HTTPConstants.CONNECT.equals(request.getMethod()) && isNumberRequests()) {
169
            incrementRequestNumber();
170
            sampler.setName(getRequestNumber() + " " + sampler.getPath());
171
        } else {
172
            sampler.setName(sampler.getPath());
173
        }
174
175
        // Set the content encoding
176
        if(contentEncoding != null) {
177
            sampler.setContentEncoding(contentEncoding);
178
        }
179
180
        // If it was a HTTP GET request, then all parameters in the URL
181
        // has been handled by the sampler.setPath above, so we just need
182
        // to do parse the rest of the request if it is not a GET request
183
        if((!HTTPConstants.CONNECT.equals(request.getMethod())) && (!HTTPConstants.GET.equals(request.getMethod()))) {
184
            // Check if it was a multipart http post request
185
            final String contentType = request.getContentType();
186
            MultipartUrlConfig urlConfig = request.getMultipartConfig(contentType);
187
            if (urlConfig != null) {
188
                urlConfig.parseArguments(postData);
189
                // Tell the sampler to do a multipart post
190
                sampler.setDoMultipartPost(true);
191
                // Remove the header for content-type and content-length, since
192
                // those values will most likely be incorrect when the sampler
193
                // performs the multipart request, because the boundary string
194
                // will change
195
                request.getHeaderManager().removeHeaderNamed(HttpRequestHdr.CONTENT_TYPE);
196
                request.getHeaderManager().removeHeaderNamed(HttpRequestHdr.CONTENT_LENGTH);
197
198
                // Set the form data
199
                sampler.setArguments(urlConfig.getArguments());
200
                // Set the file uploads
201
                sampler.setHTTPFiles(urlConfig.getHTTPFileArgs().asArray());
202
            // used when postData is pure xml (eg. an xml-rpc call) or for PUT
203
            } else if (postData.trim().startsWith("<?") || "PUT".equals(sampler.getMethod())) {
204
                sampler.addNonEncodedArgument("", postData, "");
205
            } else if (contentType == null || contentType.startsWith(HTTPConstants.APPLICATION_X_WWW_FORM_URLENCODED) ){
206
                // It is the most common post request, with parameter name and values
207
                // We also assume this if no content type is present, to be most backwards compatible,
208
                // but maybe we should only parse arguments if the content type is as expected
209
                sampler.parseArguments(postData.trim(), contentEncoding); //standard name=value postData
210
            } else if (postData.length() > 0) {
211
                if (isBinaryContent(contentType)) {
212
                    try {
213
                        File tempDir = new File(getBinaryDirectory());
214
                        File out = File.createTempFile(request.getMethod(), getBinaryFileSuffix(), tempDir);
215
                        FileUtils.writeByteArrayToFile(out,request.getRawPostData());
216
                        HTTPFileArg [] files = {new HTTPFileArg(out.getPath(),"",contentType)};
217
                        sampler.setHTTPFiles(files);
218
                    } catch (IOException e) {
219
                        log.warn("Could not create binary file: "+e);
220
                    }
221
                } else {
222
                    // Just put the whole postbody as the value of a parameter
223
                    sampler.addNonEncodedArgument("", postData, ""); //used when postData is pure xml (ex. an xml-rpc call)
224
                }
225
            }
226
        }
227
        if (log.isDebugEnabled()) {
228
            log.debug("sampler path = " + sampler.getPath());
229
        }
230
    }
231
}
(-)src/protocol/http/org/apache/jmeter/protocol/http/proxy/HttpSamplerFactory.java (+91 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *   http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
19
package org.apache.jmeter.protocol.http.proxy;
20
21
import java.lang.reflect.Modifier;
22
import java.util.HashMap;
23
import java.util.List;
24
import java.util.Map;
25
26
import org.apache.jmeter.util.JMeterUtils;
27
import org.apache.jorphan.logging.LoggingManager;
28
import org.apache.jorphan.reflect.ClassFinder;
29
import org.apache.log.Logger;
30
31
/**
32
 *
33
 */
34
public class HttpSamplerFactory {
35
    private static final Logger log = LoggingManager.getLoggerForClass();
36
37
38
    private static final SamplerCreator DEFAULT_SAMPLER_CREATOR = new DefaultSamplerCreator();
39
    
40
41
    private Map<String, SamplerCreator> samplerCreatorMap = new HashMap<String, SamplerCreator>();
42
43
    /**
44
     * 
45
     */
46
    public HttpSamplerFactory() {
47
        init();
48
    }
49
    
50
    /**
51
     * 
52
     */
53
    private void init() {
54
        try {
55
            List<String> listClasses = ClassFinder.findClassesThatExtend(
56
                    JMeterUtils.getSearchPaths(), 
57
                    new Class[] {SamplerCreator.class }); 
58
            for (String strClassName : listClasses) {
59
                Class<?> commandClass = Class.forName(strClassName);
60
                if (!Modifier.isAbstract(commandClass.getModifiers())) {
61
                    SamplerCreator creator = (SamplerCreator) commandClass.newInstance();
62
                    String[] contentTypes = creator.getManagedContentTypes();
63
                    for (String contentType : contentTypes) {
64
                        if(log.isInfoEnabled()) {
65
                            log.info("Registering samplerCreator "+commandClass.getName()+"for content type:"+contentType);
66
                        }
67
                        samplerCreatorMap.put(contentType, creator);
68
                    }
69
                }
70
            }
71
        } catch (Exception e) {
72
            log.error("Exception finding implementations of "+SamplerCreator.class, e);
73
        }
74
    }
75
76
    /**
77
     * Gets {@link SamplerCreator} for content type, if none is found returns {@link DefaultSamplerCreator}
78
     * @param request {@link HttpRequestHdr}
79
     * @param pageEncodings Map<String, String> pageEncodings
80
     * @param formEncodings  Map<String, String> formEncodings
81
     * @return SamplerCreator
82
     */
83
    public SamplerCreator getSamplerCreator(HttpRequestHdr request,
84
            Map<String, String> pageEncodings, Map<String, String> formEncodings) {
85
        SamplerCreator creator = samplerCreatorMap.get(request.getContentType());
86
        if(creator == null) {
87
            return DEFAULT_SAMPLER_CREATOR;
88
        }
89
        return creator;
90
    }
91
}
(-)src/protocol/http/org/apache/jmeter/protocol/http/proxy/SamplerCreator.java (+55 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *   http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
19
package org.apache.jmeter.protocol.http.proxy;
20
21
import java.util.Map;
22
23
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
24
25
/**
26
 * 
27
 */
28
public interface SamplerCreator {
29
    
30
    /**
31
     * @return
32
     */
33
    public String[] getManagedContentTypes();
34
35
    /**
36
     * @param request
37
     * @param pageEncodings
38
     * @param formEncodings
39
     * @return
40
     */
41
    public HTTPSamplerBase createSampler(HttpRequestHdr request,
42
            Map<String, String> pageEncodings, Map<String, String> formEncodings);
43
44
    /**
45
     * @param sampler
46
     * @param request
47
     * @param pageEncodings
48
     * @param formEncodings
49
     * @throws Exception
50
     */
51
    public void populateSampler(HTTPSamplerBase sampler,
52
            HttpRequestHdr request, Map<String, String> pageEncodings,
53
            Map<String, String> formEncodings)
54
                    throws Exception;
55
}
(-)src/protocol/http/org/apache/jmeter/protocol/http/proxy/AbstractSamplerCreator.java (+101 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *   http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
19
package org.apache.jmeter.protocol.http.proxy;
20
21
import java.util.HashSet;
22
import java.util.Set;
23
import java.util.StringTokenizer;
24
25
import org.apache.jmeter.util.JMeterUtils;
26
27
/**
28
 * 
29
 */
30
public abstract class AbstractSamplerCreator implements SamplerCreator {
31
32
    protected static final String HTTP = "http"; // $NON-NLS-1$
33
    protected static final String HTTPS = "https"; // $NON-NLS-1$
34
35
    /** Filetype to be used for the temporary binary files*/
36
    private static final String binaryFileSuffix =
37
        JMeterUtils.getPropDefault("proxy.binary.filesuffix",// $NON-NLS-1$
38
                                   ".binary"); // $NON-NLS-1$
39
40
    /** Which content-types will be treated as binary (exact match) */
41
    private static final Set<String> binaryContentTypes = new HashSet<String>();
42
43
    /** Where to store the temporary binary files */
44
    private static final String binaryDirectory =
45
        JMeterUtils.getPropDefault("proxy.binary.directory",// $NON-NLS-1$
46
                System.getProperty("user.dir")); // $NON-NLS-1$ proxy.binary.filetype=binary
47
48
    static {
49
        String binaries = JMeterUtils.getPropDefault("proxy.binary.types", // $NON-NLS-1$
50
                "application/x-amf,application/x-java-serialized-object"); // $NON-NLS-1$
51
        if (binaries.length() > 0){
52
            StringTokenizer s = new StringTokenizer(binaries,"|, ");// $NON-NLS-1$
53
            while (s.hasMoreTokens()){
54
               binaryContentTypes.add(s.nextToken());
55
            }
56
        }
57
    }
58
    
59
    /*
60
     * Optionally number the requests
61
     */
62
    private static final boolean numberRequests =
63
        JMeterUtils.getPropDefault("proxy.number.requests", false); // $NON-NLS-1$
64
65
    private static volatile int requestNumber = 0;// running number
66
    
67
68
    /**
69
     * 
70
     */
71
    public AbstractSamplerCreator() {
72
        super();
73
    }
74
75
    protected boolean isBinaryContent(String contentType) {
76
        if (contentType == null) return false;
77
        return binaryContentTypes.contains(contentType);
78
    }
79
    
80
81
    protected static int getRequestNumber() {
82
        return requestNumber;
83
    }
84
85
    protected static void incrementRequestNumber() {
86
        requestNumber++;
87
    }
88
89
    protected static boolean isNumberRequests() {
90
        return numberRequests;
91
    }
92
93
    protected String getBinaryFileSuffix() {
94
        return binaryFileSuffix;
95
    }
96
97
    protected String getBinaryDirectory() {
98
        return binaryDirectory;
99
    }
100
101
}
(-)src/protocol/http/org/apache/jmeter/protocol/http/proxy/HttpRequestHdr.java (-240 / +39 lines)
Lines 19-48 Link Here
19
package org.apache.jmeter.protocol.http.proxy;
19
package org.apache.jmeter.protocol.http.proxy;
20
20
21
import java.io.ByteArrayOutputStream;
21
import java.io.ByteArrayOutputStream;
22
import java.io.File;
23
import java.io.IOException;
22
import java.io.IOException;
24
import java.io.InputStream;
23
import java.io.InputStream;
25
import java.io.UnsupportedEncodingException;
26
import java.net.MalformedURLException;
27
import java.net.URL;
24
import java.net.URL;
28
import java.util.HashMap;
25
import java.util.HashMap;
29
import java.util.HashSet;
30
import java.util.Map;
26
import java.util.Map;
31
import java.util.Set;
32
import java.util.StringTokenizer;
27
import java.util.StringTokenizer;
33
28
34
import org.apache.commons.io.FileUtils;
35
import org.apache.commons.lang.CharUtils;
29
import org.apache.commons.lang.CharUtils;
36
import org.apache.jmeter.protocol.http.config.MultipartUrlConfig;
30
import org.apache.jmeter.protocol.http.config.MultipartUrlConfig;
37
import org.apache.jmeter.protocol.http.control.Header;
31
import org.apache.jmeter.protocol.http.control.Header;
38
import org.apache.jmeter.protocol.http.control.HeaderManager;
32
import org.apache.jmeter.protocol.http.control.HeaderManager;
39
import org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui;
40
import org.apache.jmeter.protocol.http.gui.HeaderPanel;
33
import org.apache.jmeter.protocol.http.gui.HeaderPanel;
41
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
34
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
42
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerFactory;
43
import org.apache.jmeter.protocol.http.util.ConversionUtils;
44
import org.apache.jmeter.protocol.http.util.HTTPConstants;
35
import org.apache.jmeter.protocol.http.util.HTTPConstants;
45
import org.apache.jmeter.protocol.http.util.HTTPFileArg;
46
import org.apache.jmeter.testelement.TestElement;
36
import org.apache.jmeter.testelement.TestElement;
47
import org.apache.jmeter.util.JMeterUtils;
37
import org.apache.jmeter.util.JMeterUtils;
48
import org.apache.jorphan.logging.LoggingManager;
38
import org.apache.jorphan.logging.LoggingManager;
Lines 60-91 Link Here
60
    private static final String HTTP = "http"; // $NON-NLS-1$
50
    private static final String HTTP = "http"; // $NON-NLS-1$
61
    private static final String HTTPS = "https"; // $NON-NLS-1$
51
    private static final String HTTPS = "https"; // $NON-NLS-1$
62
    private static final String PROXY_CONNECTION = "proxy-connection"; // $NON-NLS-1$
52
    private static final String PROXY_CONNECTION = "proxy-connection"; // $NON-NLS-1$
63
    private static final String CONTENT_TYPE = "content-type"; // $NON-NLS-1$
53
    public static final String CONTENT_TYPE = "content-type"; // $NON-NLS-1$
64
    private static final String CONTENT_LENGTH = "content-length"; // $NON-NLS-1$
54
    public static final String CONTENT_LENGTH = "content-length"; // $NON-NLS-1$
65
66
    /** Filetype to be used for the temporary binary files*/
67
    private static final String binaryFileSuffix =
68
        JMeterUtils.getPropDefault("proxy.binary.filesuffix",// $NON-NLS-1$
69
                                   ".binary"); // $NON-NLS-1$
70
71
    /** Which content-types will be treated as binary (exact match) */
72
    private static final Set<String> binaryContentTypes = new HashSet<String>();
73
55
74
    /** Where to store the temporary binary files */
75
    private static final String binaryDirectory =
76
        JMeterUtils.getPropDefault("proxy.binary.directory",// $NON-NLS-1$
77
                System.getProperty("user.dir")); // $NON-NLS-1$ proxy.binary.filetype=binary
78
79
    static {
80
        String binaries = JMeterUtils.getPropDefault("proxy.binary.types", // $NON-NLS-1$
81
                "application/x-amf,application/x-java-serialized-object"); // $NON-NLS-1$
82
        if (binaries.length() > 0){
83
            StringTokenizer s = new StringTokenizer(binaries,"|, ");// $NON-NLS-1$
84
            while (s.hasMoreTokens()){
85
               binaryContentTypes.add(s.nextToken());
86
            }
87
        }
88
    }
89
56
90
    /**
57
    /**
91
     * Http Request method, uppercased, e.g. GET or POST.
58
     * Http Request method, uppercased, e.g. GET or POST.
Lines 114-127 Link Here
114
81
115
    private HeaderManager headerManager;
82
    private HeaderManager headerManager;
116
83
117
    /*
118
     * Optionally number the requests
119
     */
120
    private static final boolean numberRequests =
121
        JMeterUtils.getPropDefault("proxy.number.requests", false); // $NON-NLS-1$
122
123
    private static volatile int requestNumber = 0;// running number
124
125
    public HttpRequestHdr() {
84
    public HttpRequestHdr() {
126
        this.httpSamplerName = ""; // $NON-NLS-1$
85
        this.httpSamplerName = ""; // $NON-NLS-1$
127
    }
86
    }
Lines 251-282 Link Here
251
        return headerManager;
210
        return headerManager;
252
    }
211
    }
253
212
254
    public HTTPSamplerBase getSampler(Map<String, String> pageEncodings, Map<String, String> formEncodings)
213
    public String getContentType() {
255
            throws MalformedURLException, IOException {
256
        // Instantiate the sampler
257
        HTTPSamplerBase sampler = HTTPSamplerFactory.newInstance(httpSamplerName);
258
        // Damn! A whole new GUI just to instantiate a test element?
259
        // Isn't there a beter way?
260
        HttpTestSampleGui tempGui = new HttpTestSampleGui();
261
262
        sampler.setProperty(TestElement.GUI_CLASS, tempGui.getClass().getName());
263
264
        // Populate the sampler
265
        populateSampler(sampler, pageEncodings, formEncodings);
266
267
        tempGui.configure(sampler);
268
        tempGui.modifyTestElement(sampler);
269
        // Defaults
270
        sampler.setFollowRedirects(false);
271
        sampler.setUseKeepAlive(true);
272
273
        if (log.isDebugEnabled()) {
274
            log.debug("getSampler: sampler path = " + sampler.getPath());
275
        }
276
        return sampler;
277
    }
278
279
    private String getContentType() {
280
        Header contentTypeHeader = headers.get(CONTENT_TYPE);
214
        Header contentTypeHeader = headers.get(CONTENT_TYPE);
281
        if (contentTypeHeader != null) {
215
        if (contentTypeHeader != null) {
282
            return contentTypeHeader.getValue();
216
            return contentTypeHeader.getValue();
Lines 291-297 Link Here
291
        return false;
225
        return false;
292
    }
226
    }
293
227
294
    private MultipartUrlConfig getMultipartConfig(String contentType) {
228
    public MultipartUrlConfig getMultipartConfig(String contentType) {
295
        if(isMultipart(contentType)) {
229
        if(isMultipart(contentType)) {
296
            // Get the boundary string for the multiparts from the content type
230
            // Get the boundary string for the multiparts from the content type
297
            String boundaryString = contentType.substring(contentType.toLowerCase(java.util.Locale.ENGLISH).indexOf("boundary=") + "boundary=".length());
231
            String boundaryString = contentType.substring(contentType.toLowerCase(java.util.Locale.ENGLISH).indexOf("boundary=") + "boundary=".length());
Lines 300-471 Link Here
300
        return null;
234
        return null;
301
    }
235
    }
302
236
303
    private void populateSampler(
304
            HTTPSamplerBase sampler,
305
            Map<String, String> pageEncodings, Map<String, String> formEncodings)
306
            throws MalformedURLException, UnsupportedEncodingException {
307
        sampler.setDomain(serverName());
308
        if (log.isDebugEnabled()) {
309
            log.debug("Proxy: setting server: " + sampler.getDomain());
310
        }
311
        sampler.setMethod(method);
312
        log.debug("Proxy: setting method: " + sampler.getMethod());
313
        sampler.setPort(serverPort());
314
        if (log.isDebugEnabled()) {
315
            log.debug("Proxy: setting port: " + sampler.getPort());
316
        }
317
        if (url.indexOf("//") > -1) {
318
            String protocol = url.substring(0, url.indexOf(":"));
319
            if (log.isDebugEnabled()) {
320
                log.debug("Proxy: setting protocol to : " + protocol);
321
            }
322
            sampler.setProtocol(protocol);
323
        } else if (sampler.getPort() == HTTPConstants.DEFAULT_HTTPS_PORT) {
324
            sampler.setProtocol(HTTPS);
325
            if (log.isDebugEnabled()) {
326
                log.debug("Proxy: setting protocol to https");
327
            }
328
        } else {
329
            if (log.isDebugEnabled()) {
330
                log.debug("Proxy setting default protocol to: http");
331
            }
332
            sampler.setProtocol(HTTP);
333
        }
334
335
        URL pageUrl = null;
336
        if(sampler.isProtocolDefaultPort()) {
337
            pageUrl = new URL(sampler.getProtocol(), sampler.getDomain(), getPath());
338
        }
339
        else {
340
            pageUrl = new URL(sampler.getProtocol(), sampler.getDomain(), sampler.getPort(), getPath());
341
        }
342
        String urlWithoutQuery = getUrlWithoutQuery(pageUrl);
343
344
345
        // Check if the request itself tells us what the encoding is
346
        String contentEncoding = null;
347
        String requestContentEncoding = ConversionUtils.getEncodingFromContentType(getContentType());
348
        if(requestContentEncoding != null) {
349
            contentEncoding = requestContentEncoding;
350
        }
351
        else {
352
            // Check if we know the encoding of the page
353
            if (pageEncodings != null) {
354
                synchronized (pageEncodings) {
355
                    contentEncoding = pageEncodings.get(urlWithoutQuery);
356
                }
357
            }
358
            // Check if we know the encoding of the form
359
            if (formEncodings != null) {
360
                synchronized (formEncodings) {
361
                    String formEncoding = formEncodings.get(urlWithoutQuery);
362
                    // Form encoding has priority over page encoding
363
                    if (formEncoding != null) {
364
                        contentEncoding = formEncoding;
365
                    }
366
                }
367
            }
368
        }
369
370
        // Get the post data using the content encoding of the request
371
        String postData = null;
372
        if (log.isDebugEnabled()) {
373
            if(contentEncoding != null) {
374
                log.debug("Using encoding " + contentEncoding + " for request body");
375
            }
376
            else {
377
                log.debug("No encoding found, using JRE default encoding for request body");
378
            }
379
        }
380
        if (contentEncoding != null) {
381
            postData = new String(rawPostData, contentEncoding);
382
        } else {
383
            // Use default encoding
384
            postData = new String(rawPostData);
385
        }
386
387
        if(contentEncoding != null) {
388
            sampler.setPath(getPath(), contentEncoding);
389
        }
390
        else {
391
            // Although the spec says UTF-8 should be used for encoding URL parameters,
392
            // most browser use ISO-8859-1 for default if encoding is not known.
393
            // We use null for contentEncoding, then the url parameters will be added
394
            // with the value in the URL, and the "encode?" flag set to false
395
            sampler.setPath(getPath(), null);
396
        }
397
        if (log.isDebugEnabled()) {
398
            log.debug("Proxy: setting path: " + sampler.getPath());
399
        }
400
        if (!HTTPConstants.CONNECT.equals(getMethod()) && numberRequests) {
401
            requestNumber++;
402
            sampler.setName(requestNumber + " " + sampler.getPath());
403
        } else {
404
            sampler.setName(sampler.getPath());
405
        }
406
407
        // Set the content encoding
408
        if(contentEncoding != null) {
409
            sampler.setContentEncoding(contentEncoding);
410
        }
411
412
        // If it was a HTTP GET request, then all parameters in the URL
413
        // has been handled by the sampler.setPath above, so we just need
414
        // to do parse the rest of the request if it is not a GET request
415
        if((!HTTPConstants.CONNECT.equals(getMethod())) && (!HTTPConstants.GET.equals(method))) {
416
            // Check if it was a multipart http post request
417
            final String contentType = getContentType();
418
            MultipartUrlConfig urlConfig = getMultipartConfig(contentType);
419
            if (urlConfig != null) {
420
                urlConfig.parseArguments(postData);
421
                // Tell the sampler to do a multipart post
422
                sampler.setDoMultipartPost(true);
423
                // Remove the header for content-type and content-length, since
424
                // those values will most likely be incorrect when the sampler
425
                // performs the multipart request, because the boundary string
426
                // will change
427
                getHeaderManager().removeHeaderNamed(CONTENT_TYPE);
428
                getHeaderManager().removeHeaderNamed(CONTENT_LENGTH);
429
430
                // Set the form data
431
                sampler.setArguments(urlConfig.getArguments());
432
                // Set the file uploads
433
                sampler.setHTTPFiles(urlConfig.getHTTPFileArgs().asArray());
434
            // used when postData is pure xml (eg. an xml-rpc call) or for PUT
435
            } else if (postData.trim().startsWith("<?") || "PUT".equals(sampler.getMethod())) {
436
                sampler.addNonEncodedArgument("", postData, "");
437
            } else if (contentType == null || contentType.startsWith(HTTPConstants.APPLICATION_X_WWW_FORM_URLENCODED) ){
438
                // It is the most common post request, with parameter name and values
439
                // We also assume this if no content type is present, to be most backwards compatible,
440
                // but maybe we should only parse arguments if the content type is as expected
441
                sampler.parseArguments(postData.trim(), contentEncoding); //standard name=value postData
442
            } else if (postData.length() > 0) {
443
                if (isBinaryContent(contentType)) {
444
                    try {
445
                        File tempDir = new File(binaryDirectory);
446
                        File out = File.createTempFile(method, binaryFileSuffix, tempDir);
447
                        FileUtils.writeByteArrayToFile(out,rawPostData);
448
                        HTTPFileArg [] files = {new HTTPFileArg(out.getPath(),"",contentType)};
449
                        sampler.setHTTPFiles(files);
450
                    } catch (IOException e) {
451
                        log.warn("Could not create binary file: "+e);
452
                    }
453
                } else {
454
                    // Just put the whole postbody as the value of a parameter
455
                    sampler.addNonEncodedArgument("", postData, ""); //used when postData is pure xml (ex. an xml-rpc call)
456
                }
457
            }
458
        }
459
        if (log.isDebugEnabled()) {
460
            log.debug("sampler path = " + sampler.getPath());
461
        }
462
    }
463
464
    private boolean isBinaryContent(String contentType) {
465
        if (contentType == null) return false;
466
        return binaryContentTypes.contains(contentType);
467
    }
468
469
    //
237
    //
470
    // Parsing Methods
238
    // Parsing Methods
471
    //
239
    //
Lines 475-481 Link Here
475
     *
243
     *
476
     * @return server's internet name
244
     * @return server's internet name
477
     */
245
     */
478
    private String serverName() {
246
    public String serverName() {
479
        // chop to "server.name:x/thing"
247
        // chop to "server.name:x/thing"
480
        String str = url;
248
        String str = url;
481
        int i = str.indexOf("//"); // $NON-NLS-1$
249
        int i = str.indexOf("//"); // $NON-NLS-1$
Lines 506-512 Link Here
506
     *
274
     *
507
     * @return server's port (or UNSPECIFIED if not found)
275
     * @return server's port (or UNSPECIFIED if not found)
508
     */
276
     */
509
    private int serverPort() {
277
    public int serverPort() {
510
        String str = url;
278
        String str = url;
511
        // chop to "server.name:x/thing"
279
        // chop to "server.name:x/thing"
512
        int i = str.indexOf("//");
280
        int i = str.indexOf("//");
Lines 531-537 Link Here
531
     *
299
     *
532
     * @return the path
300
     * @return the path
533
     */
301
     */
534
    private String getPath() {
302
    public String getPath() {
535
        String str = url;
303
        String str = url;
536
        int i = str.indexOf("//");
304
        int i = str.indexOf("//");
537
        if (i > 0) {
305
        if (i > 0) {
Lines 595-601 Link Here
595
//        return strBuff.toString();
363
//        return strBuff.toString();
596
//    }
364
//    }
597
365
598
    private String getUrlWithoutQuery(URL _url) {
366
    public String getUrlWithoutQuery(URL _url) {
599
        String fullUrl = _url.toString();
367
        String fullUrl = _url.toString();
600
        String urlWithoutQuery = fullUrl;
368
        String urlWithoutQuery = fullUrl;
601
        String query = _url.getQuery();
369
        String query = _url.getQuery();
Lines 605-608 Link Here
605
        }
373
        }
606
        return urlWithoutQuery;
374
        return urlWithoutQuery;
607
    }
375
    }
376
377
    /**
378
     * @return the httpSamplerName
379
     */
380
    public String getHttpSamplerName() {
381
        return httpSamplerName;
382
    }
383
384
    public byte[] getRawPostData() {
385
        return rawPostData;
386
    }
387
388
    public String getProtocol(HTTPSamplerBase sampler) {
389
        if (url.indexOf("//") > -1) {
390
            String protocol = url.substring(0, url.indexOf(":"));
391
            if (log.isDebugEnabled()) {
392
                log.debug("Proxy: setting protocol to : " + protocol);
393
            }
394
            return protocol;
395
        } else if (sampler.getPort() == HTTPConstants.DEFAULT_HTTPS_PORT) {
396
            if (log.isDebugEnabled()) {
397
                log.debug("Proxy: setting protocol to https");
398
            }
399
            return HTTPS;
400
        } else {
401
            if (log.isDebugEnabled()) {
402
                log.debug("Proxy setting default protocol to: http");
403
            }
404
            return HTTP;
405
        }
406
    }
608
}
407
}
(-)src/protocol/http/org/apache/jmeter/protocol/http/proxy/Proxy.java (-4 / +6 lines)
Lines 109-114 Link Here
109
    private static final char[] KEY_PASSWORD =
109
    private static final char[] KEY_PASSWORD =
110
        JMeterUtils.getPropDefault("proxy.cert.keypassword","password").toCharArray(); // $NON-NLS-1$ $NON-NLS-2$
110
        JMeterUtils.getPropDefault("proxy.cert.keypassword","password").toCharArray(); // $NON-NLS-1$ $NON-NLS-2$
111
111
112
    private static final HttpSamplerFactory factory = new HttpSamplerFactory();
113
112
    // Use with SSL connection
114
    // Use with SSL connection
113
    private OutputStream outStreamClient = null;
115
    private OutputStream outStreamClient = null;
114
116
Lines 202-211 Link Here
202
                request.parse(new BufferedInputStream(clientSocket.getInputStream()));
204
                request.parse(new BufferedInputStream(clientSocket.getInputStream()));
203
            }
205
            }
204
206
205
            // Populate the sampler. It is the same sampler as we sent into
207
            SamplerCreator samplerCreator = factory.getSamplerCreator(request, pageEncodings, formEncodings);
206
            // the constructor of the HttpRequestHdr instance above
208
            sampler = samplerCreator.createSampler(request, pageEncodings, formEncodings);
207
            sampler = request.getSampler(pageEncodings, formEncodings);
209
            samplerCreator.populateSampler(sampler, request, pageEncodings, formEncodings);
208
210
            
209
            /*
211
            /*
210
             * Create a Header Manager to ensure that the browsers headers are
212
             * Create a Header Manager to ensure that the browsers headers are
211
             * captured and sent to the server
213
             * captured and sent to the server

Return to bug 52674