├── .codacy.yml ├── .editorconfig ├── .github ├── CODEOWNERS ├── FUNDING.yml └── workflows │ └── gradle-build.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── checkstyle-suppressions.xml ├── checkstyle.xml ├── gradle.properties ├── gradle ├── license.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src ├── main ├── java │ └── jodd │ │ └── http │ │ ├── Buffer.java │ │ ├── Cookie.java │ │ ├── HeadersMultiMap.java │ │ ├── HttpBase.java │ │ ├── HttpConnection.java │ │ ├── HttpConnectionProvider.java │ │ ├── HttpException.java │ │ ├── HttpMultiMap.java │ │ ├── HttpProgressListener.java │ │ ├── HttpRequest.java │ │ ├── HttpResponse.java │ │ ├── HttpSession.java │ │ ├── HttpStatus.java │ │ ├── HttpTunnel.java │ │ ├── HttpUtil.java │ │ ├── ProxyInfo.java │ │ ├── Sockets.java │ │ ├── net │ │ ├── HTTPProxySocketFactory.java │ │ ├── SSLSocketHttpConnectionProvider.java │ │ ├── SocketHttpConnection.java │ │ ├── SocketHttpConnectionProvider.java │ │ ├── SocketHttpSecureConnection.java │ │ ├── Socks4ProxySocketFactory.java │ │ ├── Socks5ProxySocketFactory.java │ │ ├── TrustManagers.java │ │ └── package-info.java │ │ ├── package-info.java │ │ └── upload │ │ ├── ByteArrayUploadable.java │ │ ├── FileUpload.java │ │ ├── FileUploadFactory.java │ │ ├── FileUploadHeader.java │ │ ├── FileUploadable.java │ │ ├── MultipartRequestInputStream.java │ │ ├── MultipartStreamParser.java │ │ ├── Uploadable.java │ │ ├── impl │ │ ├── AdaptiveFileUpload.java │ │ ├── AdaptiveFileUploadFactory.java │ │ ├── DiskFileUpload.java │ │ ├── DiskFileUploadFactory.java │ │ ├── MemoryFileUpload.java │ │ ├── MemoryFileUploadFactory.java │ │ └── package-info.java │ │ └── package-info.java └── resources │ └── META-INF │ └── LICENSE └── test ├── java └── jodd │ └── http │ ├── BufferTest.java │ ├── CRLFInjectionTest.java │ ├── CookieTest.java │ ├── EchoTestServer.java │ ├── EncodingTest.java │ ├── FragmentTest.java │ ├── GoogleMapsTest.java │ ├── HttpConnectionTest.java │ ├── HttpHeaderTest.java │ ├── HttpMultiMapTest.java │ ├── HttpProgressListenerTest.java │ ├── HttpRedirectTest.java │ ├── HttpRequestTest.java │ ├── HttpSessionOfflineTest.java │ ├── HttpSessionTest.java │ ├── HttpUploadTest.java │ ├── HttpUtilTest.java │ ├── HttpsFactoryTest.java │ ├── KeepAliveTest.java │ ├── NanoHTTPD.java │ ├── NoLocationTest.java │ ├── ProxyTest.java │ ├── RawTest.java │ ├── RemoveHeaderTest.java │ ├── TestServer.java │ ├── TimeoutTest.java │ ├── TomcatServer.java │ └── fixture │ ├── Data.java │ ├── Echo2Servlet.java │ ├── Echo3Servlet.java │ ├── EchoServlet.java │ ├── RedirectServlet.java │ ├── SlowServlet.java │ ├── StringHttpRequest.java │ └── TargetServlet.java └── resources └── jodd └── http ├── 1-response.txt ├── 2-response.txt ├── 3-response.txt ├── 4-response.txt ├── 5-response.txt ├── 6-response.txt ├── answer.json └── web.xml /.codacy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | exclude_paths: 3 | - '**/test/**' 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | 8 | [*.java] 9 | indent_style = tab 10 | 11 | [*.js] 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [*.gradle] 16 | indent_style = tab -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @igr -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: igr 4 | patreon: igo_rs 5 | -------------------------------------------------------------------------------- /.github/workflows/gradle-build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | permissions: 10 | contents: read 11 | packages: write 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | jdk: [8] 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 11 20 | uses: actions/setup-java@v2 21 | with: 22 | java-version: ${{ matrix.jdk }} 23 | distribution: 'temurin' 24 | server-id: github 25 | settings-path: ${{ github.workspace }} 26 | 27 | - name: Build with Gradle 28 | uses: gradle/gradle-build-action@937999e9cc2425eddc7fd62d1053baf041147db7 29 | with: 30 | arguments: build 31 | 32 | - name: Upload coverage to Codecov 33 | uses: codecov/codecov-action@v2 34 | with: 35 | file: ./build/reports/jacoco/test/jacocoTestReport.xml 36 | flags: unittests 37 | verbose: true 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | 3 | ### Java 4 | # Compiled class file 5 | *.class 6 | 7 | # Log file 8 | *.log 9 | 10 | # BlueJ files 11 | *.ctxt 12 | 13 | # Mobile Tools for Java (J2ME) 14 | .mtj.tmp/ 15 | 16 | # Package Files # 17 | *.jar 18 | *.war 19 | *.nar 20 | *.ear 21 | *.zip 22 | *.tar.gz 23 | *.rar 24 | 25 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 26 | hs_err_pid* 27 | 28 | ### Gradle 29 | .gradle 30 | /build/ 31 | 32 | # Ignore Gradle GUI config 33 | gradle-app.setting 34 | 35 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 36 | !gradle-wrapper.jar 37 | 38 | # Cache of project 39 | .gradletasknamecache 40 | 41 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 42 | # gradle/wrapper/gradle-wrapper.properties 43 | 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2020, Oblac 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jodd HTTP 2 | 3 | [![Jodd](https://img.shields.io/badge/>-Jodd-orange)](https://github.com/oblac/jodd) 4 | ![GitHub release](https://img.shields.io/github/release/oblac/jodd-http.svg) 5 | ![Maven Central](https://img.shields.io/maven-central/v/org.jodd/jodd-http) 6 | [![javadoc](https://javadoc.io/badge2/org.jodd/jodd-http/javadoc.svg)](https://javadoc.io/doc/org.jodd/jodd-http) 7 | [![Build](https://github.com/oblac/jodd-http/actions/workflows/gradle-build.yml/badge.svg)](https://github.com/oblac/jodd-http/actions/workflows/gradle-build.yml) 8 | [![codecov](https://codecov.io/gh/oblac/jodd-http/branch/master/graph/badge.svg)](https://codecov.io/gh/oblac/jodd-http) 9 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/e3f94a223c4b4b6b8122108049e0cc3e)](https://www.codacy.com/gh/oblac/jodd-http/dashboard?utm_source=github.com&utm_medium=referral&utm_content=oblac/jodd-http&utm_campaign=Badge_Grade) 10 | [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-jodd-4183C4.svg)](https://stackoverflow.com/questions/tagged/jodd) 11 | [![BSD License](https://img.shields.io/badge/license-BSD--2--Clause-blue.svg)](https://github.com/oblac/jodd-http/blob/master/LICENSE) 12 | 13 | 🌟 Simple Java HTTP Client. 14 | 15 | 🏡 Website: [http.jodd.org](https://http.jodd.org) 16 | 17 | ❤️ For developers, by developer. 18 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, this 8 | // list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright notice, 11 | // this list of conditions and the following disclaimer in the documentation 12 | // and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | // Copyright (c) 2003-present, Jodd Team (https://jodd.org) 25 | 26 | plugins { 27 | id 'java-library' 28 | id 'maven-publish' 29 | id 'jacoco' 30 | id 'signing' 31 | id 'io.codearte.nexus-staging' version '0.21.2' 32 | id 'biz.aQute.bnd.builder' version '5.2.0' 33 | } 34 | 35 | repositories { 36 | mavenCentral() 37 | mavenLocal() 38 | } 39 | 40 | group = 'org.jodd' 41 | //version = '6.0.3-SNAPSHOT' 42 | version = '6.3.0' 43 | 44 | rootProject.description = 'Jodd HTTP Client' 45 | 46 | ext { 47 | } 48 | 49 | java { 50 | sourceCompatibility = JavaVersion.VERSION_1_8 51 | targetCompatibility = JavaVersion.VERSION_1_8 52 | withSourcesJar() 53 | withJavadocJar() 54 | } 55 | 56 | dependencies { 57 | api 'org.jodd:jodd-util:6.1.+' 58 | 59 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.+' 60 | testImplementation 'org.junit.jupiter:junit-jupiter-params:5.6.+' 61 | testImplementation 'org.mockito:mockito-core:3.5.5' 62 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.+' 63 | 64 | testImplementation 'org.apache.tomcat:tomcat-jasper:8.0.47' 65 | testImplementation 'org.apache.tomcat:tomcat-jasper-el:8.0.47' 66 | testImplementation 'org.apache.tomcat:tomcat-catalina:8.0.47' 67 | testImplementation 'org.apache.tomcat.embed:tomcat-embed-core:8.0.47' 68 | testImplementation 'org.apache.tomcat.embed:tomcat-embed-jasper:8.0.47' 69 | testImplementation 'org.apache.tomcat.embed:tomcat-embed-logging-juli:8.0.47' 70 | testImplementation 'org.apache.tomcat.embed:tomcat-embed-logging-log4j:8.0.47' 71 | 72 | testImplementation 'org.mock-server:mockserver-netty:5.2.3' 73 | } 74 | 75 | jar { 76 | bnd ('-exportcontents': 'jodd.*') 77 | manifest { 78 | attributes( 79 | 'Implementation-Title': project.name, 80 | 'Implementation-Version': project.version, 81 | 'Debug-Info': 'on', 82 | 'Built-By': 'jodd.org' 83 | ) 84 | } 85 | } 86 | 87 | javadoc { 88 | options.addStringOption('Xdoclint:none', '-quiet') 89 | if (JavaVersion.current().isJava9Compatible()) { 90 | options.addBooleanOption('html5', true) 91 | } 92 | } 93 | 94 | test { 95 | useJUnitPlatform() 96 | testLogging { 97 | events "standardOut", "passed", "skipped", "failed" 98 | showExceptions true 99 | exceptionFormat "full" 100 | showCauses true 101 | showStackTraces true 102 | 103 | afterSuite { desc, result -> 104 | if (!desc.parent) { // will match the outermost suite 105 | def output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)" 106 | def startItem = '| ', endItem = ' |' 107 | def repeatLength = startItem.length() + output.length() + endItem.length() 108 | println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' + ('-' * repeatLength)) 109 | } 110 | } 111 | } 112 | jacoco { 113 | excludes += ['*Test*', '*.?', '*.fixtures.*'] 114 | } 115 | } 116 | 117 | jacocoTestReport { 118 | reports { 119 | xml.enabled true 120 | csv.enabled false 121 | html.enabled true 122 | } 123 | } 124 | 125 | check.dependsOn jacocoTestReport 126 | 127 | // 128 | // PUBLISH 129 | // 130 | 131 | ext.admin = hasProperty('sonatypeUsername') 132 | 133 | publishing { 134 | publications { 135 | mavenJava(MavenPublication) { 136 | artifactId = 'jodd-http' 137 | from components.java 138 | versionMapping { 139 | usage('java-api') { 140 | fromResolutionOf('runtimeClasspath') 141 | } 142 | usage('java-runtime') { 143 | fromResolutionResult() 144 | } 145 | } 146 | pom { 147 | name = 'Jodd HTTP' 148 | description = 'Jodd HTTP Client' 149 | url = 'https://http.jodd.org' 150 | licenses { 151 | license { 152 | name = 'BSD-2-Clause' 153 | url = 'https://github.com/oblac/jodd-http/blob/master/LICENSE' 154 | } 155 | } 156 | developers { 157 | developer { 158 | id = 'igor' 159 | name = 'Igor Spasić' 160 | email = 'igor@jodd.org' 161 | timezone = '+1' 162 | } 163 | } 164 | scm { 165 | url = 'https://github.com/oblac/jodd-http.git' 166 | connection = 'scm:git:git://github.com/oblac/jodd-http.git' 167 | developerConnection = 'scm:git:ssh://git@github.com/oblac/jodd-http.git' 168 | } 169 | } 170 | } 171 | } 172 | repositories { 173 | maven { 174 | def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" 175 | def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/" 176 | url = version.contains('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl 177 | if (admin) { 178 | credentials { 179 | username sonatypeUsername 180 | password sonatypePassword 181 | } 182 | } 183 | } 184 | } 185 | } 186 | 187 | signing { 188 | required { admin } 189 | sign publishing.publications.mavenJava 190 | } 191 | 192 | task install(dependsOn: publishToMavenLocal) { 193 | group = 'Publishing' 194 | description = 'Installs artifacts to local Maven repository' 195 | } 196 | 197 | // 198 | // RELEASE 199 | // 200 | 201 | task release() { 202 | group 'Project' 203 | description 'Rebuilds everything for the release.' 204 | 205 | dependsOn clean 206 | dependsOn build 207 | dependsOn javadoc 208 | dependsOn jacocoTestReport 209 | } 210 | 211 | 212 | // 213 | // UTILS 214 | // 215 | 216 | apply from: "${rootProject.projectDir}/gradle/license.gradle" 217 | 218 | tasks.named('wrapper') { 219 | distributionType = Wrapper.DistributionType.ALL 220 | } 221 | 222 | static def timestamp() { 223 | return new Date().format('yyyyMMddHHmmss') 224 | } 225 | -------------------------------------------------------------------------------- /checkstyle-suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xms512M -Xmx4g -XX:MaxPermSize=1024m -XX:MaxMetaspaceSize=1g -Dkotlin.daemon.jvm.options="-Xmx1g" 2 | -------------------------------------------------------------------------------- /gradle/license.gradle: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | task license { 27 | group 'License' 28 | description 'Check for files without a license header' 29 | doLast { 30 | license(false) 31 | } 32 | } 33 | 34 | task licenseUpdate { 35 | group 'License' 36 | description 'Updates files without a license header' 37 | doLast { 38 | license(true) 39 | } 40 | } 41 | 42 | def license(overwrite) { 43 | def headerLines = file('LICENSE').readLines() 44 | 45 | // header 46 | def doubleslashHeader = "" 47 | def doubleslashPrefix = "//" 48 | def doubleslashIsBlock = false 49 | def doubleslashStart = "" 50 | def doubleslashEnd = "" 51 | headerLines.forEach { line -> 52 | line = "// " + line 53 | doubleslashHeader += line.trim() + "\n" 54 | } 55 | 56 | // header 57 | def hashHeader = "" 58 | def hashPrefix = "#" 59 | def hashIsBlock = false 60 | def hashStart = "" 61 | def hashEnd = "" 62 | headerLines.forEach { line -> 63 | line = "# " + line 64 | hashHeader += line.trim() + "\n" 65 | } 66 | 67 | // header 68 | def tagHeader = "" 69 | def tagPrefix = "" 70 | def tagIsBlock = true 71 | def tagStart = "\n" 73 | headerLines.forEach { line -> 74 | tagHeader += line.trim() + "\n" 75 | } 76 | tagHeader = tagStart + tagHeader + tagEnd 77 | 78 | 79 | // gather sources 80 | def allSource = rootProject.sourceSets.main.allSource + 81 | rootProject.sourceSets.test.allJava 82 | 83 | allSource.files.each { file -> 84 | if (!file.name.endsWith(".java")) { 85 | return 86 | } 87 | 88 | def fileNamePath = file.absolutePath 89 | fileNamePath = fileNamePath.substring(project.rootDir.absolutePath.length() + 1) 90 | 91 | // default header, java 92 | def headerContent = doubleslashHeader 93 | def headerPrefix = doubleslashPrefix 94 | def headerIsBlock = doubleslashIsBlock 95 | def headerStart = doubleslashStart 96 | def headerEnd = doubleslashEnd 97 | 98 | // apply the license 99 | if (headerContent != null) { 100 | def fileText = file.text 101 | 102 | if (fileText.startsWith(headerContent) == false) { 103 | println(fileNamePath) 104 | 105 | if (overwrite) { 106 | // remove existing header 107 | if (headerIsBlock) { 108 | int ndx = fileText.indexOf(headerEnd) 109 | if (ndx >= 0) { 110 | fileText = fileText.substring(ndx + headerEnd.length()) 111 | } 112 | } else { 113 | while (fileText.startsWith(headerPrefix)) { 114 | int ndx = fileText.indexOf("\n") 115 | fileText = fileText.substring(ndx + 1) 116 | } 117 | } 118 | 119 | // add the new header 120 | fileText = headerContent + fileText 121 | 122 | file.write(fileText) 123 | } 124 | } 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oblac/jodd-http/a07090b37b8c9c96b3c2a3411c80c0d579cefcbd/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=`expr $i + 1` 158 | done 159 | case $i in 160 | 0) set -- ;; 161 | 1) set -- "$args0" ;; 162 | 2) set -- "$args0" "$args1" ;; 163 | 3) set -- "$args0" "$args1" "$args2" ;; 164 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=`save "$@"` 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | exec "$JAVACMD" "$@" 184 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto init 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto init 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :init 68 | @rem Get command-line arguments, handling Windows variants 69 | 70 | if not "%OS%" == "Windows_NT" goto win9xME_args 71 | 72 | :win9xME_args 73 | @rem Slurp the command line arguments. 74 | set CMD_LINE_ARGS= 75 | set _SKIP=2 76 | 77 | :win9xME_args_slurp 78 | if "x%~1" == "x" goto execute 79 | 80 | set CMD_LINE_ARGS=%* 81 | 82 | :execute 83 | @rem Setup the command line 84 | 85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 86 | 87 | @rem Execute Gradle 88 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 89 | 90 | :end 91 | @rem End local scope for the variables with windows NT shell 92 | if "%ERRORLEVEL%"=="0" goto mainEnd 93 | 94 | :fail 95 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 96 | rem the _cmd.exe /c_ return code! 97 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 98 | exit /b 1 99 | 100 | :mainEnd 101 | if "%OS%"=="Windows_NT" endlocal 102 | 103 | :omega 104 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/HeadersMultiMap.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import java.util.List; 29 | 30 | public class HeadersMultiMap extends HttpMultiMap { 31 | 32 | protected HeadersMultiMap() { 33 | super(false); 34 | } 35 | 36 | /** 37 | * Adds new header value. Allows multiple values for the same name. 38 | */ 39 | public void addHeader(final String name, final String value) { 40 | List valuesList = super.getAll(name); 41 | if (valuesList.isEmpty()) { 42 | super.add(name, value); 43 | return; 44 | } 45 | super.remove(name); 46 | valuesList.add(value); 47 | super.addAll(name, valuesList); 48 | } 49 | 50 | /** 51 | * Sets the header value. Existing value will bee replaces. 52 | */ 53 | public void setHeader(final String name, final String value) { 54 | super.set(name, value); 55 | } 56 | 57 | /** 58 | * Returns header value. In case of multiple values, returns only the first value. 59 | */ 60 | public String getHeader(final String name) { 61 | return super.get(name); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/HttpConnection.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | import java.io.OutputStream; 31 | 32 | /** 33 | * Http connection. Created by {@link HttpConnectionProvider}. 34 | */ 35 | public interface HttpConnection { 36 | 37 | /** 38 | * Initializes http connection after socket is created. 39 | * Applies configurations, like {@link #setTimeout(int)}. 40 | */ 41 | public void init() throws IOException; 42 | 43 | /** 44 | * Returns connection output stream. 45 | */ 46 | public OutputStream getOutputStream() throws IOException; 47 | 48 | /** 49 | * Returns connection input stream. 50 | */ 51 | public InputStream getInputStream() throws IOException; 52 | 53 | /** 54 | * Closes connection. Ignores all exceptions. 55 | */ 56 | public void close(); 57 | 58 | /** 59 | * Sets the timeout for connections, in milliseconds. With this option set to a non-zero timeout, 60 | * connection will block for only this amount of time. If the timeout expires, an Exception is raised. 61 | * The timeout must be > 0. A timeout of zero is interpreted as an infinite timeout. 62 | */ 63 | void setTimeout(int milliseconds); 64 | 65 | } -------------------------------------------------------------------------------- /src/main/java/jodd/http/HttpConnectionProvider.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import jodd.http.net.SocketHttpConnectionProvider; 29 | 30 | import java.io.IOException; 31 | 32 | /** 33 | * Factory for {@link HttpConnection http connections}. 34 | */ 35 | public interface HttpConnectionProvider { 36 | 37 | class Implementation { 38 | private static HttpConnectionProvider httpConnectionProvider = new SocketHttpConnectionProvider(); 39 | 40 | public static void set(final HttpConnectionProvider httpConnectionProvider) { 41 | Implementation.httpConnectionProvider = httpConnectionProvider; 42 | } 43 | } 44 | 45 | /** 46 | * Returns default implementation of connection provider. 47 | */ 48 | static HttpConnectionProvider get() { 49 | return Implementation.httpConnectionProvider; 50 | } 51 | 52 | 53 | /** 54 | * Specifies {@link ProxyInfo proxy} for provide to use. 55 | */ 56 | public void useProxy(ProxyInfo proxyInfo); 57 | 58 | /** 59 | * Creates new {@link HttpConnection} 60 | * from {@link jodd.http.HttpRequest request}. 61 | */ 62 | public HttpConnection createHttpConnection(HttpRequest httpRequest) throws IOException; 63 | 64 | } -------------------------------------------------------------------------------- /src/main/java/jodd/http/HttpException.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import jodd.exception.UncheckedException; 29 | 30 | /** 31 | * HTTP exception. 32 | */ 33 | public class HttpException extends UncheckedException { 34 | 35 | public HttpException(final Throwable t) { 36 | super(t); 37 | } 38 | 39 | public HttpException(final String message) { 40 | super(message); 41 | } 42 | 43 | public HttpException(final Object networkObject, final String message) { 44 | super(networkObject.toString() + ": " + message); 45 | } 46 | 47 | public HttpException(final String message, final Throwable t) { 48 | super(message, t); 49 | } 50 | 51 | public HttpException(final Object networkObject, final String message, final Throwable t) { 52 | super(networkObject.toString() + ": " + message, t); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/HttpProgressListener.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | /** 29 | * Http upload progress listener. 30 | */ 31 | public abstract class HttpProgressListener { 32 | 33 | /** 34 | * Total size to transfer. 35 | */ 36 | protected int size; 37 | 38 | /** 39 | * Returns callback size in bytes. By default it returns 40 | * size of 1 percent of a total size. If returned size 41 | * is less then 512, it will be rounded to 512. 42 | * This is also the size of the chunk that is sent over network. 43 | */ 44 | public int callbackSize(final int size) { 45 | this.size = size; 46 | 47 | int callbackSize = (size + 50) / 100; 48 | 49 | if (callbackSize < 512) { 50 | callbackSize = 512; 51 | } 52 | 53 | return callbackSize; 54 | } 55 | 56 | /** 57 | * Callback for every sent {@link #callbackSize(int) chunk}. 58 | * Also called before and after the transfer. 59 | */ 60 | public abstract void transferred(int len); 61 | 62 | } -------------------------------------------------------------------------------- /src/main/java/jodd/http/HttpTunnel.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import jodd.io.IOUtil; 29 | 30 | import java.io.IOException; 31 | import java.io.InputStream; 32 | import java.io.OutputStream; 33 | import java.net.ServerSocket; 34 | import java.net.Socket; 35 | import java.util.concurrent.ExecutorService; 36 | import java.util.concurrent.Executors; 37 | 38 | /** 39 | * Simple HTTP tunnel base ready to be extended. 40 | */ 41 | public class HttpTunnel { 42 | 43 | /** 44 | * The number of threads that can be executed in parallel. 45 | */ 46 | protected int threadPoolSize = 10; 47 | 48 | /** 49 | * Number of incoming sockets connection that can be hold 50 | * before processing each. 51 | */ 52 | protected int socketBacklog = 100; 53 | 54 | /** 55 | * Tunnel listening port. 56 | */ 57 | protected int listenPort = 8888; 58 | 59 | /** 60 | * Target host. 61 | */ 62 | protected String targetHost = "localhost"; 63 | 64 | /** 65 | * Target port. 66 | */ 67 | protected int targetPort = 8080; 68 | 69 | protected ExecutorService executorService; 70 | protected volatile boolean running; 71 | protected ServerSocket serverSocket; 72 | 73 | /** 74 | * Starts HTTP tunnel. Method ends when the tunnel is stopped. 75 | */ 76 | public void start() throws IOException { 77 | serverSocket = new ServerSocket(listenPort, socketBacklog); 78 | serverSocket.setReuseAddress(true); 79 | executorService = Executors.newFixedThreadPool(threadPoolSize); 80 | 81 | running = true; 82 | while (running) { 83 | final Socket socket = serverSocket.accept(); 84 | socket.setKeepAlive(false); 85 | executorService.execute(onSocketConnection(socket)); 86 | } 87 | executorService.shutdown(); 88 | } 89 | 90 | /** 91 | * Invoked on incoming connection. By default returns {@link HttpTunnelConnection} 92 | * to handle the connection. May be used to return custom 93 | * handlers. 94 | */ 95 | protected Runnable onSocketConnection(final Socket socket) { 96 | return new HttpTunnelConnection(socket); 97 | } 98 | 99 | /** 100 | * Stops the tunnel, shutdowns the thread pool and closes server socket. 101 | */ 102 | public void stop() { 103 | running = false; 104 | executorService.shutdown(); 105 | try { 106 | serverSocket.close(); 107 | } catch (final IOException ignore) { 108 | } 109 | } 110 | 111 | /** 112 | * Single connection handler that performs the tunneling. 113 | */ 114 | public class HttpTunnelConnection implements Runnable { 115 | 116 | protected final Socket socket; 117 | 118 | public HttpTunnelConnection(final Socket socket) { 119 | this.socket = socket; 120 | } 121 | 122 | @Override 123 | public void run() { 124 | try { 125 | tunnel(); 126 | } catch (final IOException ioex) { 127 | ioex.printStackTrace(); 128 | } 129 | } 130 | 131 | /** 132 | * Invoked after income connection is parsed. Nothing is 133 | * changed in the request, except the target host and port. 134 | */ 135 | protected void onRequest(final HttpRequest request) { 136 | } 137 | 138 | /** 139 | * Invoked after target response is processed. Response is now 140 | * ready to be sent back to the client. The following header 141 | * parameters are changed: 142 | * 146 | */ 147 | protected void onResponse(final HttpResponse response) { 148 | } 149 | 150 | /** 151 | * Performs the tunneling. The following steps occurs: 152 | * 159 | */ 160 | protected void tunnel() throws IOException { 161 | 162 | // read request 163 | final InputStream socketInput = socket.getInputStream(); 164 | final HttpRequest request = HttpRequest.readFrom(socketInput); 165 | 166 | // open client socket to target 167 | final Socket clientSocket = Sockets.connect(targetHost, targetPort); 168 | 169 | // do request 170 | request.host(targetHost); 171 | request.port(targetPort); 172 | request.setHostHeader(); 173 | onRequest(request); 174 | 175 | // resend request to target 176 | final OutputStream out = clientSocket.getOutputStream(); 177 | request.sendTo(out); 178 | 179 | // read target response 180 | final InputStream in = clientSocket.getInputStream(); 181 | final HttpResponse response = HttpResponse.readFrom(in); 182 | 183 | // close client socket 184 | IOUtil.close(in); 185 | IOUtil.close(out); 186 | try { 187 | clientSocket.close(); 188 | } catch (final IOException ignore) { 189 | } 190 | 191 | // fix response 192 | if (response.bodyRaw() != null) { 193 | response.headerRemove("Transfer-Encoding"); 194 | response.contentLength(response.bodyRaw().length()); 195 | } 196 | 197 | // do response 198 | onResponse(response); 199 | 200 | // send response back 201 | final OutputStream socketOutput = socket.getOutputStream(); 202 | response.sendTo(socketOutput); 203 | 204 | // close socket 205 | IOUtil.close(socketInput); 206 | IOUtil.close(socketOutput); 207 | try { 208 | socket.close(); 209 | } catch (final IOException ignore) { 210 | } 211 | } 212 | } 213 | 214 | } 215 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/ProxyInfo.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | /** 29 | * Proxy information. 30 | */ 31 | public class ProxyInfo { 32 | 33 | /** 34 | * Proxy types. 35 | */ 36 | public enum ProxyType { 37 | NONE, HTTP, SOCKS4, SOCKS5 38 | } 39 | 40 | private final String proxyAddress; 41 | private final int proxyPort; 42 | private final String proxyUsername; 43 | private final String proxyPassword; 44 | private final ProxyType proxyType; 45 | 46 | public ProxyInfo(final ProxyType proxyType, final String proxyHost, final int proxyPort, final String proxyUser, final String proxyPassword) { 47 | this.proxyType = proxyType; 48 | this.proxyAddress = proxyHost; 49 | this.proxyPort = proxyPort; 50 | this.proxyUsername = proxyUser; 51 | this.proxyPassword = proxyPassword; 52 | } 53 | 54 | // ---------------------------------------------------------------- factory 55 | 56 | /** 57 | * Creates directProxy. 58 | */ 59 | public static ProxyInfo directProxy() { 60 | return new ProxyInfo(ProxyType.NONE, null, 0, null, null); 61 | } 62 | 63 | /** 64 | * Creates SOCKS4 proxy. 65 | */ 66 | public static ProxyInfo socks4Proxy(final String proxyAddress, final int proxyPort, final String proxyUser) { 67 | return new ProxyInfo(ProxyType.SOCKS4, proxyAddress, proxyPort, proxyUser, null); 68 | } 69 | 70 | /** 71 | * Creates SOCKS5 proxy. 72 | */ 73 | public static ProxyInfo socks5Proxy(final String proxyAddress, final int proxyPort, final String proxyUser, final String proxyPassword) { 74 | return new ProxyInfo(ProxyType.SOCKS5, proxyAddress, proxyPort, proxyUser, proxyPassword); 75 | } 76 | 77 | /** 78 | * Creates HTTP proxy. 79 | */ 80 | public static ProxyInfo httpProxy(final String proxyAddress, final int proxyPort, final String proxyUser, final String proxyPassword) { 81 | return new ProxyInfo(ProxyType.HTTP, proxyAddress, proxyPort, proxyUser, proxyPassword); 82 | } 83 | 84 | // ---------------------------------------------------------------- getter 85 | 86 | /** 87 | * Returns proxy type. 88 | */ 89 | public ProxyType getProxyType() { 90 | return proxyType; 91 | } 92 | 93 | /** 94 | * Returns proxy address. 95 | */ 96 | public String getProxyAddress() { 97 | return proxyAddress; 98 | } 99 | 100 | /** 101 | * Returns proxy port. 102 | */ 103 | public int getProxyPort() { 104 | return proxyPort; 105 | } 106 | 107 | /** 108 | * Returns proxy user name or null if 109 | * no authentication required. 110 | */ 111 | public String getProxyUsername() { 112 | return proxyUsername; 113 | } 114 | 115 | /** 116 | * Returns proxy password or null. 117 | */ 118 | public String getProxyPassword() { 119 | return proxyPassword; 120 | } 121 | 122 | } -------------------------------------------------------------------------------- /src/main/java/jodd/http/Sockets.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import java.io.IOException; 29 | import java.net.InetSocketAddress; 30 | import java.net.Socket; 31 | 32 | /** 33 | * Sockets factory. 34 | */ 35 | public class Sockets { 36 | 37 | /** 38 | * Creates a socket. 39 | */ 40 | public static Socket connect(final String hostname, final int port) throws IOException { 41 | final Socket socket = new Socket(); 42 | socket.connect(new InetSocketAddress(hostname, port)); 43 | return socket; 44 | } 45 | 46 | /** 47 | * Creates a socket with a timeout. 48 | */ 49 | public static Socket connect(final String hostname, final int port, final int connectionTimeout) throws IOException { 50 | final Socket socket = new Socket(); 51 | if (connectionTimeout <= 0) { 52 | socket.connect(new InetSocketAddress(hostname, port)); 53 | } 54 | else { 55 | socket.connect(new InetSocketAddress(hostname, port), connectionTimeout); 56 | } 57 | return socket; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/net/HTTPProxySocketFactory.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.net; 27 | 28 | import jodd.http.HttpException; 29 | import jodd.http.ProxyInfo; 30 | import jodd.http.Sockets; 31 | import jodd.util.Base64; 32 | 33 | import javax.net.SocketFactory; 34 | import java.io.BufferedReader; 35 | import java.io.InputStream; 36 | import java.io.StringReader; 37 | import java.net.HttpURLConnection; 38 | import java.net.InetAddress; 39 | import java.net.Socket; 40 | import java.nio.charset.StandardCharsets; 41 | import java.util.regex.Matcher; 42 | import java.util.regex.Pattern; 43 | 44 | /** 45 | * Socket factory for HTTP proxy. 46 | */ 47 | public class HTTPProxySocketFactory extends SocketFactory { 48 | 49 | private final ProxyInfo proxy; 50 | private final int connectionTimeout; 51 | 52 | public HTTPProxySocketFactory(final ProxyInfo proxy, final int connectionTimeout) { 53 | this.proxy = proxy; 54 | this.connectionTimeout = connectionTimeout; 55 | } 56 | 57 | @Override 58 | public Socket createSocket() { 59 | return new Socket(); 60 | } 61 | 62 | @Override 63 | public Socket createSocket(final String host, final int port) { 64 | return createHttpProxySocket(host, port); 65 | } 66 | 67 | @Override 68 | public Socket createSocket(final String host, final int port, final InetAddress localHost, final int localPort) { 69 | return createHttpProxySocket(host, port); 70 | } 71 | 72 | @Override 73 | public Socket createSocket(final InetAddress host, final int port) { 74 | return createHttpProxySocket(host.getHostAddress(), port); 75 | } 76 | 77 | @Override 78 | public Socket createSocket(final InetAddress address, final int port, final InetAddress localAddress, final int localPort) { 79 | return createHttpProxySocket(address.getHostAddress(), port); 80 | } 81 | 82 | private Socket createHttpProxySocket(final String host, final int port) { 83 | Socket socket = null; 84 | final String proxyAddress = proxy.getProxyAddress(); 85 | final int proxyPort = proxy.getProxyPort(); 86 | 87 | try { 88 | socket = Sockets.connect(proxyAddress, proxyPort, connectionTimeout); 89 | final String hostport = host + ":" + port; 90 | String proxyLine = ""; 91 | final String username = proxy.getProxyUsername(); 92 | 93 | if (username != null) { 94 | final String password = proxy.getProxyPassword(); 95 | proxyLine = 96 | "Proxy-Authorization: Basic " + 97 | Base64.encodeToString((username + ":" + password)) + "\r\n"; 98 | } 99 | 100 | socket.getOutputStream().write( 101 | ("CONNECT " + hostport + " HTTP/1.1\r\n" + 102 | "Host: " + hostport + "\r\n" + 103 | proxyLine + 104 | "\r\n" 105 | ).getBytes(StandardCharsets.UTF_8) 106 | ); 107 | 108 | final InputStream in = socket.getInputStream(); 109 | final StringBuilder recv = new StringBuilder(100); 110 | int nlchars = 0; 111 | 112 | do { 113 | final int i = in.read(); 114 | if (i == -1) { 115 | throw new HttpException(ProxyInfo.ProxyType.HTTP, "Invalid response"); 116 | } 117 | 118 | final char c = (char) i; 119 | recv.append(c); 120 | if (recv.length() > 1024) { 121 | throw new HttpException(ProxyInfo.ProxyType.HTTP, "Received header longer then 1024 chars"); 122 | } 123 | if ((nlchars == 0 || nlchars == 2) && c == '\r') { 124 | nlchars++; 125 | } else if ((nlchars == 1 || nlchars == 3) && c == '\n') { 126 | nlchars++; 127 | } else { 128 | nlchars = 0; 129 | } 130 | } while (nlchars != 4); 131 | 132 | final String recvStr = recv.toString(); 133 | 134 | final BufferedReader br = new BufferedReader(new StringReader(recvStr)); 135 | final String response = br.readLine(); 136 | 137 | if (response == null) { 138 | throw new HttpException(ProxyInfo.ProxyType.HTTP, "Empty proxy response"); 139 | } 140 | 141 | final Matcher m = RESPONSE_PATTERN.matcher(response); 142 | if (!m.matches()) { 143 | throw new HttpException(ProxyInfo.ProxyType.HTTP, "Unexpected proxy response"); 144 | } 145 | 146 | final int code = Integer.parseInt(m.group(1)); 147 | 148 | if (code != HttpURLConnection.HTTP_OK) { 149 | throw new HttpException(ProxyInfo.ProxyType.HTTP, "Invalid return status code: " + code); 150 | } 151 | 152 | return socket; 153 | } catch (final RuntimeException rtex) { 154 | closeSocket(socket); 155 | throw rtex; 156 | } catch (final Exception ex) { 157 | closeSocket(socket); 158 | throw new HttpException(ProxyInfo.ProxyType.HTTP, ex.toString(), ex); 159 | } 160 | 161 | } 162 | 163 | /** 164 | * Closes socket silently. 165 | */ 166 | private void closeSocket(final Socket socket) { 167 | try { 168 | if (socket != null) { 169 | socket.close(); 170 | } 171 | } catch (final Exception ignore) { 172 | } 173 | } 174 | 175 | private static final Pattern RESPONSE_PATTERN = 176 | Pattern.compile("HTTP/\\S+\\s(\\d+)\\s(.*)\\s*"); 177 | } 178 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/net/SSLSocketHttpConnectionProvider.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.net; 27 | 28 | import jodd.http.ProxyInfo; 29 | 30 | import javax.net.SocketFactory; 31 | import javax.net.ssl.SSLContext; 32 | import javax.net.ssl.SSLSocketFactory; 33 | 34 | /** 35 | * Custom SSL socket http connection provider. 36 | */ 37 | public class SSLSocketHttpConnectionProvider extends SocketHttpConnectionProvider { 38 | 39 | private final SSLSocketFactory socketFactory; 40 | 41 | public SSLSocketHttpConnectionProvider(final SSLSocketFactory sslSocketFactory) { 42 | this.socketFactory = sslSocketFactory; 43 | } 44 | 45 | public SSLSocketHttpConnectionProvider(final SSLContext sslContext) { 46 | this.socketFactory = sslContext.getSocketFactory(); 47 | } 48 | 49 | @Override 50 | protected SocketFactory resolveSocketFactory( 51 | final ProxyInfo proxy, 52 | final boolean ssl, 53 | final boolean trustAllCertificates, 54 | final int connectionTimeout) { 55 | return socketFactory; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/net/SocketHttpConnection.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.net; 27 | 28 | import jodd.http.HttpConnection; 29 | 30 | import java.io.IOException; 31 | import java.io.InputStream; 32 | import java.io.OutputStream; 33 | import java.net.Socket; 34 | 35 | /** 36 | * Socket-based {@link jodd.http.HttpConnection}. 37 | * @see SocketHttpConnectionProvider 38 | */ 39 | public class SocketHttpConnection implements HttpConnection { 40 | 41 | protected final Socket socket; 42 | 43 | public SocketHttpConnection(final Socket socket) { 44 | this.socket = socket; 45 | } 46 | 47 | @Override 48 | public void init() throws IOException { 49 | if (timeout >= 0) { 50 | socket.setSoTimeout(timeout); 51 | } 52 | } 53 | 54 | @Override 55 | public OutputStream getOutputStream() throws IOException { 56 | return socket.getOutputStream(); 57 | } 58 | 59 | @Override 60 | public InputStream getInputStream() throws IOException { 61 | return socket.getInputStream(); 62 | } 63 | 64 | @Override 65 | public void close() { 66 | try { 67 | socket.close(); 68 | } catch (Throwable ignore) { 69 | } 70 | } 71 | 72 | @Override 73 | public void setTimeout(final int milliseconds) { 74 | this.timeout = milliseconds; 75 | } 76 | 77 | /** 78 | * Returns Socket used by this connection. 79 | */ 80 | public Socket getSocket() { 81 | return socket; 82 | } 83 | 84 | private int timeout; 85 | } -------------------------------------------------------------------------------- /src/main/java/jodd/http/net/SocketHttpSecureConnection.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.net; 27 | 28 | import javax.net.ssl.SSLSocket; 29 | import java.io.IOException; 30 | 31 | public class SocketHttpSecureConnection extends SocketHttpConnection { 32 | private final SSLSocket sslSocket; 33 | 34 | public SocketHttpSecureConnection(final SSLSocket socket) { 35 | super(socket); 36 | this.sslSocket = socket; 37 | } 38 | 39 | @Override 40 | public void init() throws IOException { 41 | super.init(); 42 | 43 | sslSocket.startHandshake(); 44 | } 45 | } -------------------------------------------------------------------------------- /src/main/java/jodd/http/net/Socks4ProxySocketFactory.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.net; 27 | 28 | import jodd.http.HttpException; 29 | import jodd.http.ProxyInfo; 30 | import jodd.http.Sockets; 31 | 32 | import javax.net.SocketFactory; 33 | import java.io.InputStream; 34 | import java.io.OutputStream; 35 | import java.net.InetAddress; 36 | import java.net.Socket; 37 | 38 | /** 39 | * Socket factory for SOCKS4 proxy. This proxy does not do password authentication. 40 | * 41 | * See: http://www.openssh.com/txt/socks5.protocol for more details. 42 | */ 43 | public class Socks4ProxySocketFactory extends SocketFactory { 44 | 45 | private final ProxyInfo proxy; 46 | private final int connectionTimeout; 47 | 48 | public Socks4ProxySocketFactory(final ProxyInfo proxy, final int connectionTimeout) { 49 | this.proxy = proxy; 50 | this.connectionTimeout = connectionTimeout; 51 | } 52 | 53 | @Override 54 | public Socket createSocket() { 55 | return new Socket(); 56 | } 57 | 58 | @Override 59 | public Socket createSocket(final String host, final int port) { 60 | return createSocks4ProxySocket(host, port); 61 | } 62 | 63 | @Override 64 | public Socket createSocket(final String host, final int port, final InetAddress localHost, final int localPort) { 65 | return createSocks4ProxySocket(host, port); 66 | } 67 | 68 | @Override 69 | public Socket createSocket(final InetAddress host, final int port) { 70 | return createSocks4ProxySocket(host.getHostAddress(), port); 71 | } 72 | 73 | @Override 74 | public Socket createSocket(final InetAddress address, final int port, final InetAddress localAddress, final int localPort) { 75 | return createSocks4ProxySocket(address.getHostAddress(), port); 76 | } 77 | 78 | /** 79 | * Connects to the SOCKS4 proxy and returns proxified socket. 80 | */ 81 | private Socket createSocks4ProxySocket(final String host, final int port) { 82 | Socket socket = null; 83 | final String proxyHost = proxy.getProxyAddress(); 84 | final int proxyPort = proxy.getProxyPort(); 85 | final String user = proxy.getProxyUsername(); 86 | 87 | try { 88 | socket = Sockets.connect(proxyHost, proxyPort, connectionTimeout); 89 | 90 | final InputStream in = socket.getInputStream(); 91 | final OutputStream out = socket.getOutputStream(); 92 | 93 | socket.setTcpNoDelay(true); 94 | 95 | final byte[] buf = new byte[1024]; 96 | 97 | // 1) CONNECT 98 | 99 | int index = 0; 100 | buf[index++] = 4; 101 | buf[index++] = 1; 102 | 103 | buf[index++] = (byte) (port >>> 8); 104 | buf[index++] = (byte) (port & 0xff); 105 | 106 | final InetAddress addr = InetAddress.getByName(host); 107 | final byte[] byteAddress = addr.getAddress(); 108 | for (final byte byteAddres : byteAddress) { 109 | buf[index++] = byteAddres; 110 | } 111 | 112 | if (user != null) { 113 | System.arraycopy(user.getBytes(), 0, buf, index, user.length()); 114 | index += user.length(); 115 | } 116 | buf[index++] = 0; 117 | out.write(buf, 0, index); 118 | 119 | // 2) RESPONSE 120 | 121 | final int len = 6; 122 | int s = 0; 123 | while (s < len) { 124 | final int i = in.read(buf, s, len - s); 125 | if (i <= 0) { 126 | throw new HttpException(ProxyInfo.ProxyType.SOCKS4, "stream is closed"); 127 | } 128 | s += i; 129 | } 130 | if (buf[0] != 0) { 131 | throw new HttpException(ProxyInfo.ProxyType.SOCKS4, "proxy returned VN " + buf[0]); 132 | } 133 | if (buf[1] != 90) { 134 | try { 135 | socket.close(); 136 | } catch (final Exception ignore) { 137 | } 138 | throw new HttpException(ProxyInfo.ProxyType.SOCKS4, "proxy returned CD " + buf[1]); 139 | } 140 | 141 | final byte[] temp = new byte[2]; 142 | in.read(temp, 0, 2); 143 | 144 | return socket; 145 | } catch (final RuntimeException rtex) { 146 | closeSocket(socket); 147 | throw rtex; 148 | } catch (final Exception ex) { 149 | closeSocket(socket); 150 | throw new HttpException(ProxyInfo.ProxyType.SOCKS4, ex.toString(), ex); 151 | } 152 | } 153 | 154 | /** 155 | * Closes socket silently. 156 | */ 157 | private void closeSocket(final Socket socket) { 158 | try { 159 | if (socket != null) { 160 | socket.close(); 161 | } 162 | } catch (final Exception ignore) { 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/net/TrustManagers.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | package jodd.http.net; 26 | 27 | import javax.net.ssl.SSLEngine; 28 | import javax.net.ssl.TrustManager; 29 | import javax.net.ssl.X509ExtendedTrustManager; 30 | import java.net.Socket; 31 | import java.security.cert.X509Certificate; 32 | 33 | public class TrustManagers { 34 | /** 35 | * Array of trust managers that allow all certificates, done in Java8 proper-way. 36 | */ 37 | public static TrustManager[] TRUST_ALL_CERTS = new TrustManager[]{ 38 | new X509ExtendedTrustManager() { 39 | @Override 40 | public void checkClientTrusted(final X509Certificate[] x509Certificates, final String s) { 41 | } 42 | @Override 43 | public void checkServerTrusted(final X509Certificate[] x509Certificates, final String s) { 44 | } 45 | @Override 46 | public X509Certificate[] getAcceptedIssuers() { 47 | return null; 48 | } 49 | @Override 50 | public void checkClientTrusted(final X509Certificate[] x509Certificates, final String s, final Socket socket) { 51 | } 52 | @Override 53 | public void checkServerTrusted(final X509Certificate[] x509Certificates, final String s, final Socket socket) { 54 | } 55 | @Override 56 | public void checkClientTrusted(final X509Certificate[] x509Certificates, final String s, final SSLEngine sslEngine) { 57 | } 58 | @Override 59 | public void checkServerTrusted(final X509Certificate[] x509Certificates, final String s, final SSLEngine sslEngine) { 60 | } 61 | } 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/net/package-info.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | /** 27 | * Implementations and core HTTP stuff. 28 | */ 29 | package jodd.http.net; -------------------------------------------------------------------------------- /src/main/java/jodd/http/package-info.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | /** 27 | * Tiny, raw and simple socket-based HTTP client. 28 | */ 29 | package jodd.http; -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/ByteArrayUploadable.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.upload; 27 | 28 | import java.io.ByteArrayInputStream; 29 | import java.io.InputStream; 30 | 31 | /** 32 | * Uploadable wrapper of byte array. 33 | */ 34 | public class ByteArrayUploadable implements Uploadable { 35 | 36 | protected final byte[] byteArray; 37 | protected final String fileName; 38 | protected final String mimeType; 39 | 40 | public ByteArrayUploadable(final byte[] byteArray, final String fileName) { 41 | this.byteArray = byteArray; 42 | this.fileName = fileName; 43 | this.mimeType = null; 44 | } 45 | 46 | public ByteArrayUploadable(final byte[] byteArray, final String fileName, final String mimeType) { 47 | this.byteArray = byteArray; 48 | this.fileName = fileName; 49 | this.mimeType = mimeType; 50 | } 51 | 52 | @Override 53 | public byte[] getContent() { 54 | return byteArray; 55 | } 56 | 57 | @Override 58 | public byte[] getBytes() { 59 | return byteArray; 60 | } 61 | 62 | @Override 63 | public String getFileName() { 64 | return fileName; 65 | } 66 | 67 | @Override 68 | public String getMimeType() { 69 | return mimeType; 70 | } 71 | 72 | @Override 73 | public int getSize() { 74 | return byteArray.length; 75 | } 76 | 77 | @Override 78 | public InputStream openInputStream() { 79 | return new ByteArrayInputStream(byteArray); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/FileUpload.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.upload; 27 | 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | 31 | /** 32 | * Encapsulates base for uploaded file. Its instance may be 33 | * either valid, when it represent an uploaded file, or invalid 34 | * when uploaded file doesn't exist or there was a problem with it. 35 | */ 36 | public abstract class FileUpload { 37 | 38 | protected final MultipartRequestInputStream input; 39 | protected final int maxFileSize; 40 | protected final FileUploadHeader header; 41 | 42 | protected FileUpload(final MultipartRequestInputStream input, final int maxFileSize) { 43 | this.input = input; 44 | this.header = input.lastHeader; 45 | this.maxFileSize = maxFileSize; 46 | } 47 | 48 | // ---------------------------------------------------------------- header 49 | 50 | /** 51 | * Returns {@link FileUploadHeader} of uploaded file. 52 | */ 53 | public FileUploadHeader getHeader() { 54 | return header; 55 | } 56 | 57 | // ---------------------------------------------------------------- data 58 | 59 | /** 60 | * Returns all bytes of uploaded file. 61 | */ 62 | public abstract byte[] getFileContent() throws IOException; 63 | 64 | /** 65 | * Returns input stream of uploaded file. 66 | */ 67 | public abstract InputStream getFileInputStream() throws IOException; 68 | 69 | // ---------------------------------------------------------------- size and validity 70 | 71 | protected boolean valid; 72 | 73 | protected int size = -1; 74 | 75 | protected boolean fileTooBig; 76 | 77 | /** 78 | * Returns the file upload size or -1 if file was not uploaded. 79 | */ 80 | public int getSize() { 81 | return size; 82 | } 83 | 84 | /** 85 | * Returns true if file was uploaded. 86 | */ 87 | public boolean isUploaded() { 88 | return size != -1; 89 | } 90 | 91 | /** 92 | * Returns true if upload process went correctly. 93 | * This still does not mean that file is uploaded, e.g. when file 94 | * was not specified on the form. 95 | */ 96 | public boolean isValid() { 97 | return valid; 98 | } 99 | 100 | /** 101 | * Returns max file size or -1 if there is no max file size. 102 | */ 103 | public int getMaxFileSize() { 104 | return maxFileSize; 105 | } 106 | 107 | /** 108 | * Returns true if file is too big. File will be marked as invalid. 109 | */ 110 | public boolean isFileTooBig() { 111 | return fileTooBig; 112 | } 113 | 114 | // ---------------------------------------------------------------- status 115 | 116 | /** 117 | * Returns true if uploaded file content is stored in memory. 118 | */ 119 | public abstract boolean isInMemory(); 120 | 121 | // ---------------------------------------------------------------- process 122 | 123 | /** 124 | * Process request input stream. Note that file size is unknown at this point. 125 | * Therefore, the implementation should set the {@link #getSize() size} 126 | * attribute after successful processing. This method also must set the 127 | * {@link #isValid() valid} attribute. 128 | * 129 | * @see MultipartRequestInputStream 130 | */ 131 | protected abstract void processStream() throws IOException; 132 | 133 | // ---------------------------------------------------------------- toString 134 | 135 | /** 136 | * Returns basic information about the uploaded file. 137 | */ 138 | @Override 139 | public String toString() { 140 | return "FileUpload: uploaded=[" + isUploaded() + "] valid=[" + valid + "] field=[" + 141 | header.getFormFieldName() + "] name=[" + header.getFileName() + "] size=[" + size + ']'; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/FileUploadFactory.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.upload; 27 | 28 | /** 29 | * {@link FileUpload} factory for handling uploaded files. Implementations may 30 | * handle uploaded files differently: to store them to memory, directly to disk 31 | * or something else. 32 | */ 33 | @FunctionalInterface 34 | public interface FileUploadFactory { 35 | 36 | /** 37 | * Creates new instance of {@link FileUpload uploaded file}. 38 | */ 39 | FileUpload create(MultipartRequestInputStream input); 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/FileUploadHeader.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.upload; 27 | 28 | import jodd.io.FileNameUtil; 29 | import jodd.util.StringPool; 30 | 31 | /** 32 | * Parses file upload header. 33 | */ 34 | public class FileUploadHeader { 35 | 36 | String dataHeader; 37 | String formFieldName; 38 | 39 | String formFileName; 40 | String path; 41 | String fileName; 42 | 43 | boolean isFile; 44 | String contentType; 45 | String mimeType; 46 | String mimeSubtype; 47 | String contentDisposition; 48 | 49 | 50 | FileUploadHeader(final String dataHeader) { 51 | this.dataHeader = dataHeader; 52 | isFile = dataHeader.indexOf("filename") > 0; 53 | formFieldName = getDataFieldValue(dataHeader, "name"); 54 | if (isFile) { 55 | formFileName = getDataFieldValue(dataHeader, "filename"); 56 | if (formFileName == null) { 57 | return; 58 | } 59 | if (formFileName.length() == 0) { 60 | path = StringPool.EMPTY; 61 | fileName = StringPool.EMPTY; 62 | } 63 | int ls = FileNameUtil.indexOfLastSeparator(formFileName); 64 | if (ls == -1) { 65 | path = StringPool.EMPTY; 66 | fileName = formFileName; 67 | } else { 68 | path = formFileName.substring(0, ls); 69 | fileName = formFileName.substring(ls + 1); 70 | } 71 | if (fileName.length() > 0) { 72 | this.contentType = getContentType(dataHeader); 73 | mimeType = getMimeType(contentType); 74 | mimeSubtype = getMimeSubtype(contentType); 75 | contentDisposition = getContentDisposition(dataHeader); 76 | } 77 | } 78 | } 79 | 80 | // ---------------------------------------------------------------- utilities 81 | 82 | /** 83 | * Gets value of data field or null if field not found. 84 | */ 85 | private String getDataFieldValue(final String dataHeader, final String fieldName) { 86 | String value = null; 87 | String token = String.valueOf((new StringBuffer(String.valueOf(fieldName))).append('=').append('"')); 88 | int pos = dataHeader.indexOf(token); 89 | if (pos > 0) { 90 | int start = pos + token.length(); 91 | int end = dataHeader.indexOf('"', start); 92 | if ((start > 0) && (end > 0)) { 93 | value = dataHeader.substring(start, end); 94 | } 95 | } 96 | return value; 97 | } 98 | 99 | /** 100 | * Strips content type information from requests data header. 101 | * @param dataHeader data header string 102 | * @return content type or an empty string if no content type defined 103 | */ 104 | private String getContentType(final String dataHeader) { 105 | String token = "Content-Type:"; 106 | int start = dataHeader.indexOf(token); 107 | if (start == -1) { 108 | return StringPool.EMPTY; 109 | } 110 | start += token.length(); 111 | return dataHeader.substring(start).trim(); 112 | } 113 | 114 | private String getContentDisposition(final String dataHeader) { 115 | int start = dataHeader.indexOf(':') + 1; 116 | int end = dataHeader.indexOf(';'); 117 | return dataHeader.substring(start, end); 118 | } 119 | 120 | private String getMimeType(final String ContentType) { 121 | int pos = ContentType.indexOf('/'); 122 | if (pos == -1) { 123 | return ContentType; 124 | } 125 | return ContentType.substring(1, pos); 126 | } 127 | 128 | private String getMimeSubtype(final String ContentType) { 129 | int start = ContentType.indexOf('/'); 130 | if (start == -1) { 131 | return ContentType; 132 | } 133 | start++; 134 | return ContentType.substring(start); 135 | } 136 | 137 | 138 | // ---------------------------------------------------------------- public interface 139 | 140 | /** 141 | * Returns true if uploaded data are correctly marked as a file. 142 | * This is true if header contains string 'filename'. 143 | */ 144 | public boolean isFile() { 145 | return isFile; 146 | } 147 | 148 | /** 149 | * Returns form field name. 150 | */ 151 | public String getFormFieldName() { 152 | return formFieldName; 153 | } 154 | 155 | /** 156 | * Returns complete file name as specified at client side. 157 | */ 158 | public String getFormFilename() { 159 | return formFileName; 160 | } 161 | 162 | /** 163 | * Returns file name (base name and extension, without full path data). 164 | */ 165 | public String getFileName() { 166 | return fileName; 167 | } 168 | 169 | /** 170 | * Returns uploaded content type. It is usually in the following form:
171 | * mime_type/mime_subtype. 172 | * 173 | * @see #getMimeType() 174 | * @see #getMimeSubtype() 175 | */ 176 | public String getContentType() { 177 | return contentType; 178 | } 179 | 180 | /** 181 | * Returns file types MIME. 182 | */ 183 | public String getMimeType() { 184 | return mimeType; 185 | } 186 | 187 | /** 188 | * Returns file sub type MIME. 189 | */ 190 | public String getMimeSubtype() { 191 | return mimeSubtype; 192 | } 193 | 194 | /** 195 | * Returns content disposition. Usually it is 'form-data'. 196 | */ 197 | public String getContentDisposition() { 198 | return contentDisposition; 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/FileUploadable.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.upload; 27 | 28 | import jodd.http.HttpException; 29 | import jodd.io.FileNameUtil; 30 | import jodd.io.FileUtil; 31 | 32 | import java.io.File; 33 | import java.io.FileInputStream; 34 | import java.io.IOException; 35 | import java.io.InputStream; 36 | 37 | /** 38 | * File uploadable. 39 | */ 40 | public class FileUploadable implements Uploadable { 41 | 42 | protected final File file; 43 | protected final String fileName; 44 | protected final String mimeType; 45 | 46 | public FileUploadable(final File file) { 47 | this.file = file; 48 | this.fileName = FileNameUtil.getName(file.getName()); 49 | this.mimeType = null; 50 | } 51 | 52 | public FileUploadable(final File file, final String fileName, final String mimeType) { 53 | this.file = file; 54 | this.fileName = fileName; 55 | this.mimeType = mimeType; 56 | } 57 | 58 | @Override 59 | public File getContent() { 60 | return file; 61 | } 62 | 63 | @Override 64 | public byte[] getBytes() { 65 | try { 66 | return FileUtil.readBytes(file); 67 | } catch (IOException ioex) { 68 | throw new HttpException(ioex); 69 | } 70 | } 71 | 72 | @Override 73 | public String getFileName() { 74 | return fileName; 75 | } 76 | 77 | @Override 78 | public String getMimeType() { 79 | return mimeType; 80 | } 81 | 82 | @Override 83 | public int getSize() { 84 | return (int) file.length(); 85 | } 86 | 87 | @Override 88 | public InputStream openInputStream() throws IOException { 89 | return new FileInputStream(file); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/MultipartRequestInputStream.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.upload; 27 | 28 | import java.io.BufferedInputStream; 29 | import java.io.ByteArrayOutputStream; 30 | import java.io.IOException; 31 | import java.io.InputStream; 32 | import java.io.OutputStream; 33 | 34 | /** 35 | * Extended input stream based on buffered requests input stream. 36 | * It provides some more functions that might be useful when working 37 | * with uploaded fies. 38 | */ 39 | public class MultipartRequestInputStream extends BufferedInputStream { 40 | 41 | public MultipartRequestInputStream(final InputStream in) { 42 | super(in); 43 | } 44 | 45 | /** 46 | * Reads expected byte. Throws exception on streams end. 47 | */ 48 | public byte readByte() throws IOException { 49 | final int i = super.read(); 50 | if (i == -1) { 51 | throw new IOException("End of HTTP request stream reached"); 52 | } 53 | return (byte) i; 54 | } 55 | 56 | /** 57 | * Skips specified number of bytes. 58 | */ 59 | public void skipBytes(final int i) throws IOException { 60 | final long len = super.skip(i); 61 | if (len != i) { 62 | throw new IOException("Failed to skip data in HTTP request"); 63 | } 64 | } 65 | 66 | // ---------------------------------------------------------------- boundary 67 | 68 | protected byte[] boundary; 69 | 70 | /** 71 | * Reads boundary from the input stream. 72 | */ 73 | public byte[] readBoundary() throws IOException { 74 | final ByteArrayOutputStream boundaryOutput = new ByteArrayOutputStream(); 75 | byte b; 76 | // skip optional whitespaces 77 | while ((b = readByte()) <= ' ') { 78 | } 79 | boundaryOutput.write(b); 80 | 81 | // now read boundary chars 82 | while ((b = readByte()) != '\r') { 83 | boundaryOutput.write(b); 84 | } 85 | if (boundaryOutput.size() == 0) { 86 | throw new IOException("Problems with parsing request: invalid boundary"); 87 | } 88 | skipBytes(1); 89 | boundary = new byte[boundaryOutput.size() + 2]; 90 | System.arraycopy(boundaryOutput.toByteArray(), 0, boundary, 2, boundary.length - 2); 91 | boundary[0] = '\r'; 92 | boundary[1] = '\n'; 93 | return boundary; 94 | } 95 | 96 | // ---------------------------------------------------------------- data header 97 | 98 | protected FileUploadHeader lastHeader; 99 | 100 | public FileUploadHeader getLastHeader() { 101 | return lastHeader; 102 | } 103 | 104 | /** 105 | * Reads data header from the input stream. When there is no more 106 | * headers (i.e. end of stream reached), returns null 107 | */ 108 | public FileUploadHeader readDataHeader(final String encoding) throws IOException { 109 | final String dataHeader = readDataHeaderString(encoding); 110 | if (dataHeader != null) { 111 | lastHeader = new FileUploadHeader(dataHeader); 112 | } else { 113 | lastHeader = null; 114 | } 115 | return lastHeader; 116 | } 117 | 118 | 119 | protected String readDataHeaderString(final String encoding) throws IOException { 120 | final ByteArrayOutputStream data = new ByteArrayOutputStream(); 121 | byte b; 122 | while (true) { 123 | // end marker byte on offset +0 and +2 must be 13 124 | if ((b = readByte()) != '\r') { 125 | data.write(b); 126 | continue; 127 | } 128 | mark(4); 129 | skipBytes(1); 130 | final int i = read(); 131 | if (i == -1) { 132 | // reached end of stream 133 | return null; 134 | } 135 | if (i == '\r') { 136 | reset(); 137 | break; 138 | } 139 | reset(); 140 | data.write(b); 141 | } 142 | skipBytes(3); 143 | if (encoding != null) { 144 | return data.toString(encoding); 145 | } else { 146 | return data.toString(); 147 | } 148 | } 149 | 150 | 151 | // ---------------------------------------------------------------- copy 152 | 153 | /** 154 | * Copies bytes from this stream to some output until boundary is 155 | * reached. Returns number of copied bytes. It will throw an exception 156 | * for any irregular behaviour. 157 | */ 158 | public int copyAll(final OutputStream out) throws IOException { 159 | int count = 0; 160 | while (true) { 161 | final byte b = readByte(); 162 | if (isBoundary(b)) { 163 | break; 164 | } 165 | out.write(b); 166 | count++; 167 | } 168 | return count; 169 | } 170 | 171 | /** 172 | * Copies max or less number of bytes to output stream. Useful for determining 173 | * if uploaded file is larger then expected. 174 | */ 175 | public int copyMax(final OutputStream out, final int maxBytes) throws IOException { 176 | int count = 0; 177 | while (true) { 178 | final byte b = readByte(); 179 | if (isBoundary(b)) { 180 | break; 181 | } 182 | out.write(b); 183 | count++; 184 | if (count == maxBytes) { 185 | return count; 186 | } 187 | } 188 | return count; 189 | } 190 | 191 | /** 192 | * Skips to the boundary and returns total number of bytes skipped. 193 | */ 194 | public int skipToBoundary() throws IOException { 195 | int count = 0; 196 | while (true) { 197 | final byte b = readByte(); 198 | count++; 199 | if (isBoundary(b)) { 200 | break; 201 | } 202 | } 203 | return count; 204 | } 205 | 206 | /** 207 | * Checks if the current byte (i.e. one that was read last) represents 208 | * the very first byte of the boundary. 209 | */ 210 | public boolean isBoundary(byte b) throws IOException { 211 | final int boundaryLen = boundary.length; 212 | mark(boundaryLen + 1); 213 | int bpos = 0; 214 | while (b == boundary[bpos]) { 215 | b = readByte(); 216 | bpos++; 217 | if (bpos == boundaryLen) { 218 | return true; // boundary found! 219 | } 220 | } 221 | reset(); 222 | return false; 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/Uploadable.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.upload; 27 | 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | 31 | /** 32 | * Common interface of uploaded content for {@link jodd.http.HttpBase#form() form parameters}. 33 | * All supported objects that can be uploaded using 34 | * the {@link jodd.http.HttpBase#form(String, Object)} has to 35 | * be wrapped with this interface. 36 | */ 37 | public interface Uploadable { 38 | 39 | /** 40 | * Returns the original content. 41 | */ 42 | public T getContent(); 43 | 44 | /** 45 | * Returns content bytes. 46 | */ 47 | public byte[] getBytes(); 48 | 49 | /** 50 | * Returns content file name. 51 | * If null, the field's name will be used. 52 | */ 53 | public String getFileName(); 54 | 55 | /** 56 | * Returns MIME type. If null, 57 | * MIME type will be determined from 58 | * {@link #getFileName() file name's} extension. 59 | */ 60 | public String getMimeType(); 61 | 62 | /** 63 | * Returns size in bytes. 64 | */ 65 | public int getSize(); 66 | 67 | /** 68 | * Opens InputStream. User is responsible 69 | * for closing it. 70 | */ 71 | public InputStream openInputStream() throws IOException; 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/impl/AdaptiveFileUploadFactory.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.upload.impl; 27 | 28 | import jodd.http.upload.FileUpload; 29 | import jodd.http.upload.FileUploadFactory; 30 | import jodd.http.upload.MultipartRequestInputStream; 31 | 32 | import java.io.File; 33 | 34 | /** 35 | * 36 | * Factory for {@link AdaptiveFileUpload}. 37 | */ 38 | public class AdaptiveFileUploadFactory implements FileUploadFactory { 39 | 40 | protected int memoryThreshold = 8192; 41 | protected File uploadPath; 42 | protected int maxFileSize = 102400; 43 | protected boolean breakOnError; 44 | protected String[] fileExtensions; 45 | protected boolean allowFileExtensions = true; 46 | 47 | /** 48 | * {@inheritDoc} 49 | */ 50 | @Override 51 | public FileUpload create(final MultipartRequestInputStream input) { 52 | return new AdaptiveFileUpload(input, memoryThreshold, uploadPath, maxFileSize, breakOnError, fileExtensions, allowFileExtensions); 53 | } 54 | 55 | // ---------------------------------------------------------------- properties 56 | 57 | public int getMemoryThreshold() { 58 | return memoryThreshold; 59 | } 60 | /** 61 | * Specifies per file memory limit for keeping uploaded files in the memory. 62 | */ 63 | public AdaptiveFileUploadFactory setMemoryThreshold(final int memoryThreshold) { 64 | if (memoryThreshold >= 0) { 65 | this.memoryThreshold = memoryThreshold; 66 | } 67 | return this; 68 | } 69 | 70 | public File getUploadPath() { 71 | return uploadPath; 72 | } 73 | 74 | /** 75 | * Specifies the upload path. If set to null default 76 | * system TEMP path will be used. 77 | */ 78 | public AdaptiveFileUploadFactory setUploadPath(final File uploadPath) { 79 | this.uploadPath = uploadPath; 80 | return this; 81 | } 82 | 83 | public int getMaxFileSize() { 84 | return maxFileSize; 85 | } 86 | 87 | /** 88 | * Sets maximum file upload size. Setting to -1 89 | * disables this constraint. 90 | */ 91 | public AdaptiveFileUploadFactory setMaxFileSize(final int maxFileSize) { 92 | this.maxFileSize = maxFileSize; 93 | return this; 94 | } 95 | 96 | public boolean isBreakOnError() { 97 | return breakOnError; 98 | } 99 | 100 | public AdaptiveFileUploadFactory setBreakOnError(final boolean breakOnError) { 101 | this.breakOnError = breakOnError; 102 | return this; 103 | } 104 | 105 | /** 106 | * Specifies if upload should break on error. 107 | */ 108 | public AdaptiveFileUploadFactory breakOnError(final boolean breakOnError) { 109 | this.breakOnError = breakOnError; 110 | return this; 111 | } 112 | 113 | /** 114 | * Allow or disallow set of file extensions. Only one rule can be active at time, 115 | * which means user can only specify extensions that are either allowed or disallowed. 116 | * Setting this value to null will turn this feature off. 117 | */ 118 | public AdaptiveFileUploadFactory setFileExtensions(final String[] fileExtensions, final boolean allow) { 119 | this.fileExtensions = fileExtensions; 120 | this.allowFileExtensions = allow; 121 | return this; 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/impl/DiskFileUpload.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.upload.impl; 27 | 28 | import jodd.http.upload.FileUpload; 29 | import jodd.http.upload.MultipartRequestInputStream; 30 | import jodd.io.FileUtil; 31 | import jodd.io.IOUtil; 32 | 33 | import java.io.BufferedInputStream; 34 | import java.io.BufferedOutputStream; 35 | import java.io.File; 36 | import java.io.FileInputStream; 37 | import java.io.FileOutputStream; 38 | import java.io.IOException; 39 | import java.io.InputStream; 40 | import java.io.OutputStream; 41 | 42 | /** 43 | * {@link FileUpload} that saves uploaded files directly to destination folder. 44 | */ 45 | public class DiskFileUpload extends FileUpload { 46 | 47 | protected final File destFolder; 48 | 49 | DiskFileUpload(final MultipartRequestInputStream input, final File destinationFolder, final int maxFileSize) { 50 | super(input, maxFileSize); 51 | this.destFolder = destinationFolder; 52 | } 53 | 54 | /** 55 | * Returns false as uploaded file is stored on disk. 56 | */ 57 | @Override 58 | public boolean isInMemory() { 59 | return false; 60 | } 61 | 62 | /** 63 | * Returns destination folder. 64 | */ 65 | public File getDestinationFolder() { 66 | return destFolder; 67 | } 68 | 69 | /** 70 | * Returns uploaded and saved file. 71 | */ 72 | public File getFile() { 73 | return file; 74 | } 75 | 76 | protected File file; 77 | 78 | /** 79 | * Returns files content from disk file. 80 | * If error occurs, it returns null 81 | */ 82 | @Override 83 | public byte[] getFileContent() throws IOException { 84 | return FileUtil.readBytes(file); 85 | } 86 | 87 | /** 88 | * Returns new buffered file input stream. 89 | */ 90 | @Override 91 | public InputStream getFileInputStream() throws IOException { 92 | return new BufferedInputStream(new FileInputStream(file)); 93 | } 94 | 95 | @Override 96 | protected void processStream() throws IOException { 97 | file = new File(destFolder, header.getFileName()); 98 | final OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); 99 | 100 | size = 0; 101 | try { 102 | if (maxFileSize == -1) { 103 | size = input.copyAll(out); 104 | } else { 105 | size = input.copyMax(out, maxFileSize + 1); // one more byte to detect larger files 106 | if (size > maxFileSize) { 107 | fileTooBig = true; 108 | valid = false; 109 | input.skipToBoundary(); 110 | return; 111 | } 112 | } 113 | valid = true; 114 | } finally { 115 | IOUtil.close(out); 116 | } 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/impl/DiskFileUploadFactory.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.upload.impl; 27 | 28 | import jodd.http.upload.FileUpload; 29 | import jodd.http.upload.FileUploadFactory; 30 | import jodd.http.upload.MultipartRequestInputStream; 31 | import jodd.util.SystemUtil; 32 | 33 | import java.io.File; 34 | import java.io.IOException; 35 | 36 | /** 37 | * Factory for {@link jodd.http.upload.impl.DiskFileUpload} 38 | */ 39 | public class DiskFileUploadFactory implements FileUploadFactory { 40 | 41 | protected File destFolder; 42 | 43 | protected int maxFileSize = 102400; 44 | 45 | public DiskFileUploadFactory() throws IOException { 46 | this(SystemUtil.info().getTempDir()); 47 | } 48 | 49 | public DiskFileUploadFactory(final String destFolder) throws IOException { 50 | this(destFolder, 102400); 51 | 52 | } 53 | 54 | public DiskFileUploadFactory(final String destFolder, final int maxFileSize) throws IOException { 55 | setUploadDir(destFolder); 56 | this.maxFileSize = maxFileSize; 57 | } 58 | 59 | 60 | public DiskFileUploadFactory setUploadDir(String destFolder) throws IOException { 61 | if (destFolder == null) { 62 | destFolder = SystemUtil.info().getTempDir(); 63 | } 64 | final File destination = new File(destFolder); 65 | if (!destination.exists()) { 66 | destination.mkdirs(); 67 | } 68 | if (!destination.isDirectory()) { 69 | throw new IOException("Invalid destination folder: " + destFolder); 70 | } 71 | this.destFolder = destination; 72 | return this; 73 | } 74 | 75 | public int getMaxFileSize() { 76 | return maxFileSize; 77 | } 78 | 79 | /** 80 | * Sets maximum file upload size. Setting to -1 will disable this constraint. 81 | */ 82 | public DiskFileUploadFactory setMaxFileSize(final int maxFileSize) { 83 | this.maxFileSize = maxFileSize; 84 | return this; 85 | } 86 | 87 | /** 88 | * {@inheritDoc} 89 | */ 90 | @Override 91 | public FileUpload create(final MultipartRequestInputStream input) { 92 | return new DiskFileUpload(input, destFolder, maxFileSize); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/impl/MemoryFileUpload.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.upload.impl; 27 | 28 | 29 | import jodd.http.upload.FileUpload; 30 | import jodd.http.upload.MultipartRequestInputStream; 31 | 32 | import java.io.ByteArrayInputStream; 33 | import java.io.ByteArrayOutputStream; 34 | import java.io.IOException; 35 | import java.io.InputStream; 36 | 37 | /** 38 | * {@link FileUpload} that stores uploaded files in memory byte array. 39 | */ 40 | public class MemoryFileUpload extends FileUpload { 41 | 42 | MemoryFileUpload(final MultipartRequestInputStream input, final int maxFileSize) { 43 | super(input, maxFileSize); 44 | } 45 | 46 | // ---------------------------------------------------------------- logic 47 | 48 | protected byte[] data; 49 | 50 | /** 51 | * Returns byte array containing uploaded file data. 52 | */ 53 | @Override 54 | public byte[] getFileContent() { 55 | return data; 56 | } 57 | 58 | /** 59 | * Returns true as uploaded file is stored in memory. 60 | */ 61 | @Override 62 | public boolean isInMemory() { 63 | return true; 64 | } 65 | 66 | /** 67 | * Returns byte array input stream. 68 | */ 69 | @Override 70 | public InputStream getFileInputStream() { 71 | return new ByteArrayInputStream(data); 72 | } 73 | 74 | /** 75 | * Reads data from input stream into byte array and stores file size. 76 | */ 77 | @Override 78 | public void processStream() throws IOException { 79 | final ByteArrayOutputStream out = new ByteArrayOutputStream(); 80 | size = 0; 81 | if (maxFileSize == -1) { 82 | size += input.copyAll(out); 83 | } else { 84 | size += input.copyMax(out, maxFileSize + 1); // one more byte to detect larger files 85 | if (size > maxFileSize) { 86 | fileTooBig = true; 87 | valid = false; 88 | input.skipToBoundary(); 89 | return; 90 | } 91 | } 92 | data = out.toByteArray(); 93 | size = data.length; 94 | valid = true; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/impl/MemoryFileUploadFactory.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.upload.impl; 27 | 28 | import jodd.http.upload.FileUpload; 29 | import jodd.http.upload.FileUploadFactory; 30 | import jodd.http.upload.MultipartRequestInputStream; 31 | 32 | /** 33 | * Factory for {@link jodd.net.upload.impl.MemoryFileUpload}. 34 | */ 35 | public class MemoryFileUploadFactory implements FileUploadFactory { 36 | 37 | protected int maxFileSize = 102400; 38 | 39 | public int getMaxFileSize() { 40 | return maxFileSize; 41 | } 42 | 43 | /** 44 | * Sets maximum file upload size. Setting to -1 will disable this constraint. 45 | */ 46 | public MemoryFileUploadFactory setMaxFileSize(final int maxFileSize) { 47 | this.maxFileSize = maxFileSize; 48 | return this; 49 | } 50 | 51 | /** 52 | * {@inheritDoc} 53 | */ 54 | @Override 55 | public FileUpload create(final MultipartRequestInputStream input) { 56 | return new MemoryFileUpload(input, maxFileSize); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/impl/package-info.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | /** 27 | * Various implementations of uploaded files and their factories. 28 | */ 29 | package jodd.io.upload.impl; -------------------------------------------------------------------------------- /src/main/java/jodd/http/upload/package-info.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | /** 27 | * Uploadable content and few implementations. 28 | */ 29 | package jodd.http.upload; 30 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2003-present, Jodd Team (https://jodd.org) 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/CRLFInjectionTest.java: -------------------------------------------------------------------------------- 1 | package jodd.http; 2 | 3 | import jodd.net.URLCoder; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static org.junit.jupiter.api.Assertions.assertEquals; 7 | 8 | class CRLFInjectionTest { 9 | 10 | @Test 11 | void testGet_crlf_injection() { 12 | String url = "http://127.0.0.1:6379/ \rfoo";//"HTTP/1.1\r\nHost: 127.0.0.13:1099\r\n\r\nSLAVE OF inhann.top:6379\r\n\r\nPOST / "; 13 | HttpRequest req = HttpRequest.get(url); 14 | 15 | assertEquals("GET /%20%0Dfoo HTTP/1.1", req.toString().split("\n")[0].trim()); 16 | } 17 | 18 | @Test 19 | void testGet_crlf_injection_path() { 20 | String url = "http://127.0.0.1:6379/"; 21 | HttpRequest req = HttpRequest.get(url).path(" \rfoo"); 22 | 23 | assertEquals("GET /%20%0Dfoo HTTP/1.1", req.toString().split("\n")[0].trim()); 24 | } 25 | 26 | @Test 27 | void testGet_crlf_injection2() { 28 | String path = " HTTP/1.1\n" + 29 | "Host: 127.0.0.13:1099\n" + 30 | "\n" + 31 | "SLAVE OF inhann.top:6379\n" + 32 | "\n" + 33 | "POST /"; 34 | String url = "http://127.0.0.1:6379/" + path; 35 | HttpRequest req = HttpRequest.get(url); 36 | 37 | assertEquals("GET /" + URLCoder.encodePath(path) + " HTTP/1.1", req.toString().split("\n")[0].trim()); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/CookieTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import org.junit.jupiter.api.Test; 29 | 30 | import static org.junit.jupiter.api.Assertions.assertEquals; 31 | import static org.junit.jupiter.api.Assertions.assertTrue; 32 | 33 | class CookieTest { 34 | 35 | @Test 36 | void testCookieParsing() { 37 | Cookie cookie = new Cookie("name=value"); 38 | 39 | assertEquals("name", cookie.getName()); 40 | assertEquals("value", cookie.getValue()); 41 | assertEquals(null, cookie.getExpires()); 42 | 43 | cookie = new Cookie("name2=value2; Expires=Wed, 09 Jun 2021 10:18:14 GMT"); 44 | 45 | assertEquals("name2", cookie.getName()); 46 | assertEquals("value2", cookie.getValue()); 47 | assertEquals("Wed, 09 Jun 2021 10:18:14 GMT", cookie.getExpires()); 48 | 49 | cookie = new Cookie("LSID=DQAAAEaem_vYg; Path=/accounts; Secure; Expires=Wed, 13 Jan 2021 22:23:01 GMT; HttpOnly"); 50 | 51 | assertEquals("LSID", cookie.getName()); 52 | assertEquals("DQAAAEaem_vYg", cookie.getValue()); 53 | assertEquals("/accounts", cookie.getPath()); 54 | assertTrue(cookie.isSecure()); 55 | assertTrue(cookie.isHttpOnly()); 56 | } 57 | 58 | @Test 59 | void test395() { 60 | Cookie cookie = new Cookie("name=value;"); 61 | 62 | assertEquals("name", cookie.getName()); 63 | assertEquals("value", cookie.getValue()); 64 | 65 | cookie = new Cookie("name=value; "); 66 | 67 | assertEquals("name", cookie.getName()); 68 | assertEquals("value", cookie.getValue()); 69 | 70 | cookie = new Cookie("p_skey=UIJeeZgODkPQgiVcwHJBhq9mYrZC9JdpYF6SCZ3fNfY_; PATH=/; DOMAIN=mail.qq.com; ;"); 71 | 72 | assertEquals("p_skey", cookie.getName()); 73 | assertEquals("UIJeeZgODkPQgiVcwHJBhq9mYrZC9JdpYF6SCZ3fNfY_", cookie.getValue()); 74 | } 75 | 76 | @Test 77 | void testSpecialCookieValues() { 78 | Cookie cookie = new Cookie("name=value"); 79 | 80 | assertEquals("name", cookie.getName()); 81 | assertEquals("value", cookie.getValue()); 82 | 83 | cookie = new Cookie("name=value;"); 84 | 85 | assertEquals("name", cookie.getName()); 86 | assertEquals("value", cookie.getValue()); 87 | 88 | // duplicated value 89 | 90 | cookie = new Cookie("name=value;a=b;"); 91 | 92 | assertEquals("name", cookie.getName()); 93 | assertEquals("value", cookie.getValue()); 94 | 95 | // empty value 96 | 97 | cookie = new Cookie("name="); 98 | 99 | assertEquals("name", cookie.getName()); 100 | assertEquals("", cookie.getValue()); 101 | 102 | // empty name 103 | 104 | cookie = new Cookie("=value"); 105 | 106 | assertEquals(null, cookie.getName()); 107 | assertEquals(null, cookie.getValue()); 108 | } 109 | 110 | @Test 111 | void testSetGetCookieFromRequest() { 112 | final HttpRequest request = new HttpRequest(); 113 | request.cookies(new Cookie("one", "two"), new Cookie("one2", "two2")); 114 | 115 | final Cookie[] cookies = request.cookies(); 116 | assertEquals(2, cookies.length); 117 | 118 | assertEquals("one", cookies[0].getName()); 119 | assertEquals("two", cookies[0].getValue()); 120 | 121 | assertEquals("one2", cookies[1].getName()); 122 | assertEquals("two2", cookies[1].getValue()); 123 | 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/EchoTestServer.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import java.io.File; 29 | import java.io.IOException; 30 | import java.util.Properties; 31 | 32 | public class EchoTestServer extends NanoHTTPD { 33 | 34 | public EchoTestServer() throws IOException { 35 | super(8081, new File(".")); 36 | } 37 | 38 | public String uri; 39 | 40 | public String method; 41 | 42 | public Properties header; 43 | 44 | public Properties params; 45 | 46 | public Properties files; 47 | 48 | public Response serve(String uri, String method, Properties header, Properties parms, Properties files) { 49 | String msg = method + " " + uri; 50 | 51 | this.uri = uri; 52 | this.method = method; 53 | this.header = header; 54 | this.params = parms; 55 | this.files = files; 56 | 57 | return new NanoHTTPD.Response(HTTP_OK, MIME_HTML, msg); 58 | } 59 | } -------------------------------------------------------------------------------- /src/test/java/jodd/http/FragmentTest.java: -------------------------------------------------------------------------------- 1 | package jodd.http; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.assertEquals; 6 | 7 | class FragmentTest { 8 | 9 | @Test 10 | void testFragment() { 11 | final HttpRequest request = HttpRequest.get("https://studioharrison.com/#product-group"); 12 | 13 | assertEquals("/", request.path); 14 | assertEquals("product-group", request.fragment()); 15 | 16 | assertEquals("https://studioharrison.com/#product-group", request.url()); 17 | } 18 | 19 | @Test 20 | void testFragmentWithQuery() { 21 | final HttpRequest request = HttpRequest.get("https://studioharrison.com/foo?me=1#foo"); 22 | 23 | assertEquals("/foo", request.path); 24 | assertEquals("foo", request.fragment()); 25 | 26 | assertEquals("https://studioharrison.com/foo?me=1#foo", request.url()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/GoogleMapsTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import jodd.io.FileUtil; 29 | import org.junit.jupiter.api.Test; 30 | 31 | import java.io.ByteArrayInputStream; 32 | import java.io.IOException; 33 | import java.net.URL; 34 | 35 | import static org.junit.jupiter.api.Assertions.assertEquals; 36 | import static org.junit.jupiter.api.Assertions.fail; 37 | 38 | class GoogleMapsTest { 39 | 40 | @Test 41 | void testNoBody() throws IOException { 42 | /*HttpResponse httpResponse = HttpRequest.get("http://maps.googleapis.com/maps/api/geocode/json") 43 | .query("address", "14621") 44 | .query("sensor", "false") 45 | .send(); 46 | */ 47 | URL data = RawTest.class.getResource("2-response.txt"); 48 | byte[] fileContent = FileUtil.readBytes(data.getFile()); 49 | 50 | HttpResponse httpResponse = HttpResponse.readFrom(new ByteArrayInputStream(fileContent)); 51 | 52 | try { 53 | httpResponse.bodyText(); 54 | } catch (Exception ex) { 55 | fail(ex.toString()); 56 | } 57 | 58 | assertEquals("", httpResponse.bodyText()); 59 | } 60 | 61 | @Test 62 | void testNoContentLength() throws IOException { 63 | URL data = RawTest.class.getResource("3-response.txt"); 64 | byte[] fileContent = FileUtil.readBytes(data.getFile()); 65 | 66 | HttpResponse httpResponse = HttpResponse.readFrom(new ByteArrayInputStream(fileContent)); 67 | 68 | assertEquals("Body!", httpResponse.bodyText()); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/HttpConnectionTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import jodd.http.upload.ByteArrayUploadable; 29 | import jodd.io.FileUtil; 30 | import jodd.net.MimeTypes; 31 | import jodd.util.StringUtil; 32 | import org.junit.jupiter.api.Test; 33 | 34 | import java.io.File; 35 | import java.io.IOException; 36 | import java.nio.charset.StandardCharsets; 37 | 38 | import static org.junit.jupiter.api.Assertions.assertEquals; 39 | import static org.junit.jupiter.api.Assertions.assertNotNull; 40 | 41 | class HttpConnectionTest { 42 | 43 | @Test 44 | void testEcho() throws IOException { 45 | final EchoTestServer echoTestServer = new EchoTestServer(); 46 | 47 | final HttpResponse response = HttpRequest.get("http://localhost:8081/hello?id=12").send(); 48 | 49 | assertEquals(200, response.statusCode()); 50 | assertEquals("OK", response.statusPhrase()); 51 | 52 | assertEquals("GET", echoTestServer.method); 53 | assertEquals("/hello", echoTestServer.uri); 54 | assertEquals(1, echoTestServer.params.size()); 55 | assertEquals("12", echoTestServer.params.get("id")); 56 | 57 | assertEquals("GET /hello", response.bodyRaw()); 58 | 59 | echoTestServer.stop(); 60 | } 61 | 62 | @Test 63 | void testUpload() throws IOException { 64 | final EchoTestServer echoTestServer = new EchoTestServer(); 65 | 66 | final File file = FileUtil.createTempFile(); 67 | file.deleteOnExit(); 68 | 69 | FileUtil.writeString(file, "upload тест"); 70 | assertEquals("upload тест", FileUtil.readString(file)); 71 | 72 | final HttpResponse response = HttpRequest 73 | .post("http://localhost:8081/hello") 74 | .form("id", "12") 75 | .form("file", file) 76 | .send(); 77 | 78 | assertEquals(200, response.statusCode()); 79 | assertEquals("OK", response.statusPhrase()); 80 | 81 | assertEquals("POST", echoTestServer.method); 82 | assertEquals("12", echoTestServer.params.get("id")); 83 | final File uploadedFile = new File(echoTestServer.files.get("file").toString()); 84 | assertNotNull(uploadedFile); 85 | assertEquals("upload тест", FileUtil.readString(uploadedFile)); 86 | 87 | assertEquals("POST /hello", response.bodyRaw()); 88 | 89 | echoTestServer.stop(); 90 | file.delete(); 91 | } 92 | 93 | @Test 94 | void testUploadWithUploadable() throws IOException { 95 | final EchoTestServer echoTestServer = new EchoTestServer(); 96 | 97 | final HttpResponse response = HttpRequest 98 | .post("http://localhost:8081/hello") 99 | .multipart(true) 100 | .form("id", "12") 101 | .form("file", new ByteArrayUploadable( 102 | "upload тест".getBytes(StandardCharsets.UTF_8), "d ст", MimeTypes.MIME_TEXT_PLAIN)) 103 | .send(); 104 | 105 | assertEquals(200, response.statusCode()); 106 | assertEquals("OK", response.statusPhrase()); 107 | 108 | assertEquals("POST", echoTestServer.method); 109 | assertEquals("12", echoTestServer.params.get("id")); 110 | final File uploadedFile = new File(echoTestServer.files.get("file").toString()); 111 | assertNotNull(uploadedFile); 112 | assertEquals("upload тест", FileUtil.readString(uploadedFile)); 113 | 114 | assertEquals("POST /hello", response.bodyRaw()); 115 | 116 | echoTestServer.stop(); 117 | } 118 | 119 | @Test 120 | void testUploadWithMonitor() throws IOException { 121 | final EchoTestServer echoTestServer = new EchoTestServer(); 122 | 123 | final File file = FileUtil.createTempFile(); 124 | file.deleteOnExit(); 125 | 126 | FileUtil.writeString(file, StringUtil.repeat('A', 1024)); 127 | 128 | final StringBuilder sb = new StringBuilder(); 129 | 130 | final HttpResponse response = HttpRequest 131 | .post("http://localhost:8081/hello") 132 | .form("id", "12") 133 | .form("file", file) 134 | .monitor(new HttpProgressListener() { 135 | @Override 136 | public void transferred(final int len) { 137 | sb.append(":").append(len); 138 | } 139 | }) 140 | .send(); 141 | 142 | assertEquals(200, response.statusCode()); 143 | assertEquals("OK", response.statusPhrase()); 144 | 145 | echoTestServer.stop(); 146 | file.delete(); 147 | 148 | assertEquals(":0:512:1024:148", StringUtil.substring(sb.toString(), 0, -1)); 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/HttpHeaderTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import org.junit.jupiter.api.Test; 29 | 30 | import static org.junit.jupiter.api.Assertions.assertEquals; 31 | import static org.junit.jupiter.api.Assertions.assertTrue; 32 | 33 | public class HttpHeaderTest { 34 | 35 | @Test 36 | void testSettingHostsHeader_changeWithSet() { 37 | final HttpRequest httpRequest = HttpRequest.post("jodd.site"); 38 | 39 | assertEquals("jodd.site", httpRequest.host()); 40 | // calling toString as it will set the HEADER 41 | assertTrue(httpRequest.toString().contains("jodd.site")); 42 | 43 | assertEquals("jodd.site", httpRequest.header(HttpRequest.HEADER_HOST)); 44 | 45 | // change 46 | httpRequest.set("oblac.rs"); 47 | 48 | // is the header changed? first check the header 49 | assertEquals("oblac.rs", httpRequest.host()); 50 | assertEquals("oblac.rs", httpRequest.header(HttpRequest.HEADER_HOST)); 51 | // the regenerated request should work 52 | assertTrue(httpRequest.toString().contains("oblac.rs")); 53 | // after the generation 54 | assertEquals("oblac.rs", httpRequest.header(HttpRequest.HEADER_HOST)); 55 | } 56 | 57 | @Test 58 | void testSettingHostsHeader_changeWithHost() { 59 | final HttpRequest httpRequest = HttpRequest.post("jodd.site"); 60 | 61 | assertEquals("jodd.site", httpRequest.host()); 62 | // calling toString as it will set the HEADER 63 | assertTrue(httpRequest.toString().contains("jodd.site")); 64 | 65 | assertEquals("jodd.site", httpRequest.header(HttpRequest.HEADER_HOST)); 66 | 67 | // change 68 | httpRequest.host("oblac.rs"); 69 | 70 | // is the header changed? first check the header 71 | assertEquals("oblac.rs", httpRequest.host()); 72 | assertEquals("oblac.rs", httpRequest.header(HttpRequest.HEADER_HOST)); 73 | // the regenerated request should work 74 | assertTrue(httpRequest.toString().contains("oblac.rs")); 75 | // after the generation 76 | assertEquals("oblac.rs", httpRequest.header(HttpRequest.HEADER_HOST)); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/HttpMultiMapTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import org.junit.jupiter.api.Test; 29 | 30 | import java.util.Iterator; 31 | import java.util.List; 32 | import java.util.Map; 33 | 34 | import static org.junit.jupiter.api.Assertions.assertEquals; 35 | import static org.junit.jupiter.api.Assertions.assertFalse; 36 | import static org.junit.jupiter.api.Assertions.assertNull; 37 | import static org.junit.jupiter.api.Assertions.assertTrue; 38 | import static org.junit.jupiter.api.Assertions.fail; 39 | 40 | class HttpMultiMapTest { 41 | 42 | @Test 43 | void testAdd() { 44 | HttpMultiMap mm = HttpMultiMap.newCaseInsensitiveMap(); 45 | 46 | mm.add("One", "one"); 47 | mm.add("Two", "two"); 48 | 49 | assertEquals(2, mm.size()); 50 | assertEquals("one", mm.get("one")); 51 | assertEquals("two", mm.get("two")); 52 | } 53 | 54 | @Test 55 | void testAddSameName() { 56 | HttpMultiMap mm = HttpMultiMap.newCaseInsensitiveMap(); 57 | 58 | mm.add("One", "one"); 59 | mm.add("one", "two"); 60 | 61 | assertEquals(1, mm.size()); 62 | assertEquals("two", mm.get("one")); 63 | 64 | List all = mm.getAll("one"); 65 | assertEquals(2, all.size()); 66 | assertEquals("one", all.get(0)); 67 | assertEquals("two", all.get(1)); 68 | 69 | mm.add("one", "three"); 70 | all = mm.getAll("one"); 71 | assertEquals(3, all.size()); 72 | assertEquals("one", all.get(0)); 73 | assertEquals("two", all.get(1)); 74 | assertEquals("three", all.get(2)); 75 | } 76 | 77 | @Test 78 | void testMissing() { 79 | HttpMultiMap mm = HttpMultiMap.newCaseInsensitiveMap(); 80 | 81 | assertNull(mm.get("xxx")); 82 | } 83 | 84 | @Test 85 | void testIterator() { 86 | HttpMultiMap mm = HttpMultiMap.newCaseInsensitiveMap(); 87 | 88 | mm.add("One", "one"); 89 | mm.add("one", "two"); 90 | mm.add("two", "2."); 91 | mm.add("one", "three"); 92 | 93 | assertEquals(2, mm.size()); 94 | 95 | Iterator> i = mm.iterator(); 96 | 97 | assertTrue(i.hasNext()); 98 | assertEquals("one", i.next().getValue()); 99 | assertEquals("two", i.next().getValue()); 100 | assertEquals("2.", i.next().getValue()); 101 | assertEquals("three", i.next().getValue()); 102 | assertFalse(i.hasNext()); 103 | 104 | try { 105 | i.next(); 106 | fail("error"); 107 | } catch (Exception ignore) {} 108 | 109 | mm.clear(); 110 | i = mm.iterator(); 111 | assertFalse(i.hasNext()); 112 | } 113 | 114 | 115 | @Test 116 | void testNullValues() { 117 | HttpMultiMap hmm = HttpMultiMap.newCaseInsensitiveMap(); 118 | 119 | assertFalse(hmm.contains("one")); 120 | 121 | hmm.add("one", null); 122 | 123 | assertNull(hmm.get("one")); 124 | assertTrue(hmm.contains("one")); 125 | 126 | hmm.add("one", null); 127 | 128 | assertNull(hmm.get("one")); 129 | assertTrue(hmm.contains("one")); 130 | 131 | hmm.set("one", "1"); 132 | 133 | assertEquals("1", hmm.get("one")); 134 | assertTrue(hmm.contains("one")); 135 | } 136 | 137 | @Test 138 | void testParametersNumber() { 139 | HttpMultiMap hmm = HttpMultiMap.newCaseInsensitiveMap(); 140 | 141 | for (int i = 0; i < 30; i++) { 142 | hmm.add(String.valueOf(i), "!" + i); 143 | } 144 | 145 | assertEquals(30, hmm.size()); 146 | } 147 | 148 | @Test 149 | void testLetterCaseInsensitive() { 150 | HttpMultiMap mm = HttpMultiMap.newCaseInsensitiveMap(); 151 | 152 | mm.add("one", "1.1"); 153 | mm.add("one", "1.1.1"); 154 | mm.add("One", "1.2"); 155 | 156 | assertEquals(1, mm.size()); 157 | 158 | assertEquals("1.2", mm.get("one")); 159 | assertEquals("1.2", mm.get("ONE")); 160 | assertEquals("1.2", mm.get("One")); 161 | 162 | List list = mm.getAll("ONE"); 163 | 164 | assertEquals(3, list.size()); 165 | 166 | assertEquals(1, mm.names().size()); 167 | assertEquals(3, mm.entries().size()); 168 | } 169 | 170 | @Test 171 | void testLetterCaseSensitive() { 172 | HttpMultiMap mm = HttpMultiMap.newCaseSensitiveMap(); 173 | 174 | mm.add("one", "1.1"); 175 | mm.add("one", "1.1.1"); 176 | mm.add("One", "1.2"); 177 | 178 | assertEquals(2, mm.size()); 179 | 180 | assertEquals("1.1.1", mm.get("one")); 181 | assertNull(mm.get("ONE")); 182 | assertEquals("1.2", mm.get("One")); 183 | 184 | List list = mm.getAll("ONE"); 185 | assertEquals(0, list.size()); 186 | 187 | list = mm.getAll("one"); 188 | assertEquals(2, list.size()); 189 | 190 | assertEquals(2, mm.names().size()); 191 | assertEquals(3, mm.entries().size()); 192 | } 193 | 194 | } 195 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/HttpProgressListenerTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import org.junit.jupiter.api.Test; 29 | 30 | import static org.junit.jupiter.api.Assertions.assertEquals; 31 | 32 | class HttpProgressListenerTest { 33 | 34 | @Test 35 | void testHttpProgressListener() { 36 | HttpProgressListener hpl = new HttpProgressListener() { 37 | @Override 38 | public void transferred(int len) { 39 | 40 | } 41 | }; 42 | 43 | assertEquals(512, hpl.callbackSize(0)); 44 | assertEquals(512, hpl.callbackSize(1000)); 45 | assertEquals(512, hpl.callbackSize(51200)); 46 | assertEquals(512, hpl.callbackSize(51201)); 47 | 48 | assertEquals(1024, hpl.callbackSize(102400)); 49 | assertEquals(1024, hpl.callbackSize(102401)); 50 | assertEquals(1024, hpl.callbackSize(102449)); 51 | 52 | assertEquals(1025, hpl.callbackSize(102450)); 53 | assertEquals(1025, hpl.callbackSize(102499)); 54 | assertEquals(1025, hpl.callbackSize(102500)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/HttpRedirectTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import org.junit.jupiter.api.AfterAll; 29 | import org.junit.jupiter.api.BeforeAll; 30 | import org.junit.jupiter.api.Test; 31 | 32 | import static org.junit.jupiter.api.Assertions.assertEquals; 33 | import static org.junit.jupiter.api.Assertions.assertNotNull; 34 | 35 | class HttpRedirectTest { 36 | 37 | static TestServer testServer; 38 | 39 | @BeforeAll 40 | static void startServer() throws Exception { 41 | testServer = new TomcatServer(); 42 | testServer.start(); 43 | } 44 | 45 | @AfterAll 46 | static void stopServer() throws Exception { 47 | testServer.stop(); 48 | } 49 | 50 | @Test 51 | void testRedirect() { 52 | final HttpRequest httpRequest = HttpRequest.get("localhost:8173/redirect"); 53 | 54 | HttpResponse httpResponse = httpRequest.send(); 55 | 56 | assertEquals(302, httpResponse.statusCode); 57 | 58 | final HttpSession httpSession = new HttpSession(); 59 | 60 | httpSession.sendRequest( 61 | HttpRequest.get("localhost:8173/redirect")); 62 | 63 | httpResponse = httpSession.getHttpResponse(); 64 | 65 | assertNotNull(httpResponse); 66 | assertEquals("target!", httpResponse.bodyRaw()); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/HttpSessionOfflineTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import org.junit.jupiter.api.Test; 29 | 30 | import static org.junit.jupiter.api.Assertions.assertEquals; 31 | 32 | class HttpSessionOfflineTest { 33 | 34 | @Test 35 | void testDefaultParameters() { 36 | HttpSession httpSession = new HttpSession(); 37 | httpSession.setDefaultHeader("aaa", "123"); 38 | 39 | HttpRequest request = HttpRequest.get("foo.com"); 40 | request.header("bbb", "987"); 41 | 42 | httpSession.addDefaultHeaders(request); 43 | 44 | assertEquals(4, request.headerNames().size()); 45 | assertEquals("123", request.header("aaa")); 46 | assertEquals("987", request.header("bbb")); 47 | } 48 | 49 | @Test 50 | void testDefaultParametersOverwrite() { 51 | HttpSession httpSession = new HttpSession(); 52 | httpSession.setDefaultHeader("aaa", "123"); 53 | 54 | HttpRequest request = HttpRequest.get("foo.com"); 55 | request.header("aaa", "987"); 56 | 57 | httpSession.addDefaultHeaders(request); 58 | 59 | assertEquals(3, request.headerNames().size()); 60 | assertEquals("987", request.header("aaa")); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/HttpSessionTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import org.junit.jupiter.api.AfterAll; 29 | import org.junit.jupiter.api.BeforeAll; 30 | import org.junit.jupiter.api.Test; 31 | 32 | import static org.junit.jupiter.api.Assertions.assertEquals; 33 | import static org.junit.jupiter.api.Assertions.assertNotNull; 34 | 35 | class HttpSessionTest { 36 | 37 | static TestServer testServer; 38 | 39 | @BeforeAll 40 | static void startServer() throws Exception { 41 | testServer = new TomcatServer(); 42 | testServer.start(); 43 | } 44 | 45 | @AfterAll 46 | static void stopServer() throws Exception { 47 | testServer.stop(); 48 | } 49 | 50 | @Test 51 | void testSessions() { 52 | final HttpSession httpSession = new HttpSession(); 53 | 54 | httpSession.sendRequest( 55 | HttpRequest 56 | .get("localhost:8173/echo?id=17") 57 | .cookies(new Cookie("waffle", "jam")) 58 | .bodyText("hello")); 59 | 60 | final HttpResponse httpResponse = httpSession.getHttpResponse(); 61 | 62 | assertNotNull(httpResponse); 63 | assertEquals("hello", httpResponse.bodyRaw()); 64 | 65 | final Cookie[] cookies = httpResponse.cookies(); 66 | assertEquals(1, cookies.length); 67 | 68 | assertEquals("waffle", cookies[0].getName()); 69 | assertEquals("jam!", cookies[0].getValue()); 70 | } 71 | 72 | @Test 73 | void testSessionRedirect() { 74 | final HttpSession httpSession = new HttpSession(); 75 | 76 | httpSession.sendRequest(HttpRequest.get("localhost:8173/redirect")); 77 | 78 | final HttpResponse httpResponse = httpSession.getHttpResponse(); 79 | 80 | assertEquals(200, httpResponse.statusCode()); 81 | assertEquals("target!", httpResponse.bodyRaw()); 82 | 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/HttpUploadTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import jodd.io.FileUtil; 29 | import org.junit.jupiter.api.AfterAll; 30 | import org.junit.jupiter.api.BeforeAll; 31 | import org.junit.jupiter.api.Test; 32 | 33 | import java.io.File; 34 | import java.io.IOException; 35 | 36 | import static org.junit.jupiter.api.Assertions.assertTrue; 37 | 38 | class HttpUploadTest { 39 | 40 | static TestServer testServer; 41 | 42 | @BeforeAll 43 | static void startServer() throws Exception { 44 | testServer = new TomcatServer(); 45 | testServer.start(); 46 | } 47 | 48 | @AfterAll 49 | static void stopServer() throws Exception { 50 | testServer.stop(); 51 | } 52 | 53 | 54 | @Test 55 | void uploadTest() throws IOException { 56 | File temp1 = FileUtil.createTempFile(); 57 | FileUtil.writeString(temp1, "Temp1 content"); 58 | File temp2 = FileUtil.createTempFile(); 59 | FileUtil.writeString(temp2, "Temp2 content"); 60 | 61 | temp1.deleteOnExit(); 62 | temp2.deleteOnExit(); 63 | 64 | HttpRequest httpRequest = HttpRequest.post("localhost:8173/echo") 65 | .form( 66 | "title", "test", 67 | "description", "Upload test", 68 | "file1", temp1, 69 | "file2", temp2 70 | ); 71 | 72 | 73 | HttpResponse httpResponse = httpRequest.send(); 74 | String body = httpResponse.bodyText(); 75 | 76 | assertTrue(body.contains("Temp1 content")); 77 | assertTrue(body.contains("Temp2 content")); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/HttpsFactoryTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import jodd.http.net.SSLSocketHttpConnectionProvider; 29 | import org.junit.jupiter.api.Test; 30 | 31 | import javax.net.ssl.SSLSocketFactory; 32 | import java.io.IOException; 33 | import java.net.InetAddress; 34 | import java.net.Socket; 35 | import java.net.UnknownHostException; 36 | import java.util.concurrent.atomic.AtomicBoolean; 37 | 38 | import static org.junit.jupiter.api.Assertions.assertTrue; 39 | 40 | class HttpsFactoryTest { 41 | 42 | @Test 43 | void testCustomSSLSocketHttpConnectionProvider() { 44 | final AtomicBoolean atomicBoolean = new AtomicBoolean(); 45 | 46 | final SSLSocketFactory sslSocketFactory = new SSLSocketFactory() { 47 | @Override 48 | public String[] getDefaultCipherSuites() { 49 | return new String[0]; 50 | } 51 | 52 | @Override 53 | public String[] getSupportedCipherSuites() { 54 | return new String[0]; 55 | } 56 | 57 | @Override 58 | public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException { 59 | atomicBoolean.set(true); 60 | return null; 61 | } 62 | 63 | @Override 64 | public Socket createSocket(String s, int i) throws IOException, UnknownHostException { 65 | atomicBoolean.set(true); 66 | return null; 67 | } 68 | 69 | @Override 70 | public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException, UnknownHostException { 71 | atomicBoolean.set(true); 72 | return null; 73 | } 74 | 75 | @Override 76 | public Socket createSocket(InetAddress inetAddress, int i) throws IOException { 77 | atomicBoolean.set(true); 78 | return null; 79 | } 80 | 81 | @Override 82 | public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException { 83 | atomicBoolean.set(true); 84 | return null; 85 | } 86 | }; 87 | 88 | try { 89 | HttpRequest.get("https://google.com") 90 | .withConnectionProvider(new SSLSocketHttpConnectionProvider(sslSocketFactory)) 91 | .open(); 92 | } 93 | catch (NullPointerException npe) { 94 | } 95 | 96 | assertTrue(atomicBoolean.get()); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/NoLocationTest.java: -------------------------------------------------------------------------------- 1 | package jodd.http; 2 | 3 | import jodd.http.fixture.StringHttpRequest; 4 | import org.junit.jupiter.api.Test; 5 | 6 | 7 | import static org.junit.jupiter.api.Assertions.assertEquals; 8 | 9 | class NoLocationTest { 10 | 11 | @Test 12 | void testNoLocationInResponse() { 13 | HttpRequest httpRequest = StringHttpRequest.create( 14 | "HTTP/1.1 302 OK\n" + 15 | "Connection: close\n" + 16 | "\n"); 17 | HttpResponse response = httpRequest.followRedirects(true).send(); 18 | assertEquals(302, response.statusCode()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/ProxyTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import io.netty.handler.codec.http.HttpHeaders; 29 | import jodd.http.net.SocketHttpConnectionProvider; 30 | import org.junit.jupiter.api.AfterEach; 31 | import org.junit.jupiter.api.BeforeEach; 32 | import org.junit.jupiter.api.Disabled; 33 | import org.junit.jupiter.api.Test; 34 | import org.junit.jupiter.api.condition.EnabledOnOs; 35 | import org.junit.jupiter.api.condition.OS; 36 | import org.mockserver.integration.ClientAndProxy; 37 | import org.mockserver.integration.ClientAndServer; 38 | import org.mockserver.model.Header; 39 | 40 | import static org.junit.jupiter.api.Assertions.assertEquals; 41 | import static org.junit.jupiter.api.Assertions.assertTrue; 42 | import static org.mockserver.integration.ClientAndProxy.startClientAndProxy; 43 | import static org.mockserver.integration.ClientAndServer.startClientAndServer; 44 | import static org.mockserver.model.HttpRequest.request; 45 | import static org.mockserver.model.HttpResponse.response; 46 | import static org.mockserver.verify.VerificationTimes.exactly; 47 | 48 | class ProxyTest { 49 | 50 | private ClientAndProxy proxy; 51 | private ClientAndServer mockServer; 52 | 53 | @BeforeEach 54 | void startProxy() { 55 | mockServer = startClientAndServer(1080); 56 | proxy = startClientAndProxy(1090); 57 | setupMockServer(); 58 | } 59 | 60 | @AfterEach 61 | void stopProxy() { 62 | proxy.stop(); 63 | mockServer.stop(); 64 | } 65 | 66 | @Test 67 | void testDirect() { 68 | final HttpResponse response = HttpRequest.get("http://localhost:1080/get_books").send(); 69 | assertEquals(200, response.statusCode()); 70 | assertTrue(response.bodyRaw().contains("Tatum")); 71 | proxy.verify(request().withPath("/get_books"), exactly(0)); 72 | } 73 | 74 | @Test 75 | @EnabledOnOs({OS.MAC}) 76 | void testDirectHttps() { 77 | final HttpResponse response = HttpRequest.get("https://localhost:1080/get_books").trustAllCerts(true).send(); 78 | assertEquals(200, response.statusCode()); 79 | assertTrue(response.bodyRaw().contains("Tatum")); 80 | proxy.verify(request().withPath("/get_books"), exactly(0)); 81 | } 82 | 83 | @Test 84 | @Disabled 85 | void testHttpProxy() { 86 | final SocketHttpConnectionProvider s = new SocketHttpConnectionProvider(); 87 | s.useProxy(ProxyInfo.httpProxy("localhost", 1090, null, null)); 88 | 89 | final HttpResponse response = HttpRequest.get("http://localhost:1080/get_books") 90 | .withConnectionProvider(s) 91 | .send(); 92 | assertEquals(200, response.statusCode()); 93 | assertTrue(response.bodyRaw().contains("Tatum")); 94 | } 95 | 96 | @Test 97 | void testSocks5Proxy() { 98 | final SocketHttpConnectionProvider s = new SocketHttpConnectionProvider(); 99 | s.useProxy(ProxyInfo.socks5Proxy("localhost", 1090, null, null)); 100 | 101 | final HttpResponse response = HttpRequest.get("http://localhost:1080/get_books") 102 | .withConnectionProvider(s) 103 | .send(); 104 | assertEquals(200, response.statusCode()); 105 | assertTrue(response.bodyRaw().contains("Tatum")); 106 | proxy.verify(request().withPath("/get_books"), exactly(1)); 107 | } 108 | 109 | @Test 110 | @EnabledOnOs({OS.MAC}) 111 | void testSocks5ProxyWithHttps() { 112 | final SocketHttpConnectionProvider s = new SocketHttpConnectionProvider(); 113 | s.useProxy(ProxyInfo.socks5Proxy("localhost", 1090, null, null)); 114 | 115 | final HttpResponse response = HttpRequest.get("https://localhost:1080/get_books") 116 | .withConnectionProvider(s) 117 | .trustAllCerts(true) 118 | .send(); 119 | assertEquals(200, response.statusCode()); 120 | assertTrue(response.bodyRaw().contains("Tatum")); 121 | proxy.verify(request().withPath("/get_books"), exactly(1)); 122 | } 123 | 124 | private void setupMockServer() { 125 | mockServer 126 | .when( 127 | request() 128 | .withPath("/get_books") 129 | ) 130 | .respond( 131 | response() 132 | .withHeaders( 133 | new Header(HttpHeaders.Names.CONTENT_TYPE,"application/json") 134 | ) 135 | .withBody("" + 136 | "[\n" + 137 | " {\n" + 138 | " \"id\": \"1\",\n" + 139 | " \"title\": \"Xenophon's imperial fiction : on the education of Cyrus\",\n" + 140 | " \"author\": \"James Tatum\",\n" + 141 | " \"isbn\": \"0691067570\",\n" + 142 | " \"publicationDate\": \"1989\"\n" + 143 | " },\n" + 144 | " {\n" + 145 | " \"id\": \"2\",\n" + 146 | " \"title\": \"You are here : personal geographies and other maps of the imagination\",\n" + 147 | " \"author\": \"Katharine A. Harmon\",\n" + 148 | " \"isbn\": \"1568984308\",\n" + 149 | " \"publicationDate\": \"2004\"\n" + 150 | " },\n" + 151 | " {\n" + 152 | " \"id\": \"3\",\n" + 153 | " \"title\": \"You just don't understand : women and men in conversation\",\n" + 154 | " \"author\": \"Deborah Tannen\",\n" + 155 | " \"isbn\": \"0345372050\",\n" + 156 | " \"publicationDate\": \"1990\"\n" + 157 | " }" + 158 | "]") 159 | ); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/RawTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import jodd.io.FileUtil; 29 | import jodd.util.StringUtil; 30 | import org.junit.jupiter.api.Test; 31 | 32 | import java.io.ByteArrayInputStream; 33 | import java.io.IOException; 34 | import java.net.URL; 35 | 36 | import static org.junit.jupiter.api.Assertions.assertEquals; 37 | import static org.junit.jupiter.api.Assertions.assertFalse; 38 | import static org.junit.jupiter.api.Assertions.assertNotNull; 39 | import static org.junit.jupiter.api.Assertions.assertTrue; 40 | 41 | class RawTest { 42 | 43 | @Test 44 | void testRawResponse1() throws IOException { 45 | final URL data = RawTest.class.getResource("1-response.txt"); 46 | 47 | String fileContent = FileUtil.readString(data.getFile()); 48 | 49 | fileContent = StringUtil.replace(fileContent, "\r\n", "\n"); 50 | 51 | final HttpResponse response = HttpResponse.readFrom(new ByteArrayInputStream(fileContent.getBytes("UTF-8"))); 52 | 53 | final HttpMultiMap headers = response.headers; 54 | assertEquals(7, headers.size()); 55 | 56 | assertEquals("no-cache", headers.get("pragma")); 57 | assertEquals("Sat, 23 Mar 2013 23:34:18 GMT", headers.get("date")); 58 | assertEquals("max-age=0, must-revalidate, no-cache, no-store, private, post-check=0, pre-check=0", 59 | headers.get("cache-control")); 60 | assertEquals("no-cache", headers.get("pragma")); 61 | assertEquals("Thu, 01 Jan 1970 00:00:00 GMT", headers.get("expires")); 62 | assertEquals("text/html;charset=UTF-8", headers.get("content-type")); 63 | assertEquals("close", headers.get("connection")); 64 | assertEquals("102", headers.get("content-length")); 65 | 66 | assertEquals("no-cache", response.header("Pragma")); 67 | assertEquals("text/html;charset=UTF-8" , response.contentType()); 68 | assertEquals("text/html" , response.mediaType()); 69 | assertEquals("UTF-8" , response.charset()); 70 | 71 | assertNotNull(response.contentLength()); 72 | 73 | final String rawBody = response.bodyRaw(); 74 | final String textBody = response.bodyText(); 75 | 76 | assertTrue(rawBody.startsWith("")); 77 | assertTrue(rawBody.endsWith("")); 78 | 79 | assertTrue(rawBody.contains("This is UTF8 Encoding.")); 80 | assertFalse(rawBody.contains("Тхис ис УТФ8 Енцодинг.")); 81 | assertTrue(textBody.contains("Тхис ис УТФ8 Енцодинг.")); 82 | 83 | assertEquals(77, textBody.length()); 84 | 85 | final int len = textBody.getBytes("UTF-8").length; 86 | 87 | assertEquals(94, rawBody.length()); 88 | assertEquals(len, rawBody.length()); 89 | } 90 | 91 | @Test 92 | void testRawResponse4() throws IOException { 93 | final URL data = RawTest.class.getResource("4-response.txt"); 94 | 95 | String fileContent = FileUtil.readString(data.getFile()); 96 | 97 | fileContent = StringUtil.replace(fileContent, "\n", "\r\n"); 98 | fileContent = StringUtil.replace(fileContent, "\r\r\n", "\r\n"); 99 | 100 | final HttpResponse response = HttpResponse.readFrom(new ByteArrayInputStream(fileContent.getBytes("UTF-8"))); 101 | 102 | final String body = response.bodyText(); 103 | 104 | assertEquals( 105 | "Wikipedia in\n" + 106 | "\n" + 107 | "chunks.", body.replace("\r\n", "\n")); 108 | } 109 | 110 | 111 | @Test 112 | void testRawResponse5() throws IOException { 113 | final URL data = RawTest.class.getResource("5-response.txt"); 114 | 115 | String fileContent = FileUtil.readString(data.getFile()); 116 | 117 | fileContent = StringUtil.replace(fileContent, "\n", "\r\n"); 118 | fileContent = StringUtil.replace(fileContent, "\r\r\n", "\r\n"); 119 | 120 | final HttpResponse response = HttpResponse.readFrom(new ByteArrayInputStream(fileContent.getBytes("UTF-8"))); 121 | 122 | final String body = response.bodyText(); 123 | 124 | assertEquals( 125 | "Wikipedia in\n" + 126 | "\n" + 127 | "chunks.", body.replace("\r\n", "\n")); 128 | 129 | assertEquals("TheData", response.header("SomeAfterHeader")); 130 | } 131 | 132 | @Test 133 | void testRawResponse6() throws IOException { 134 | final URL data = RawTest.class.getResource("6-response.txt"); 135 | 136 | String fileContent = FileUtil.readString(data.getFile()); 137 | 138 | fileContent = StringUtil.replace(fileContent, "\n", "\r\n"); 139 | fileContent = StringUtil.replace(fileContent, "\r\r\n", "\r\n"); 140 | 141 | final HttpResponse response = HttpResponse.readFrom(new ByteArrayInputStream(fileContent.getBytes("UTF-8"))); 142 | 143 | assertEquals(200, response.statusCode()); 144 | assertEquals("", response.statusPhrase); 145 | 146 | final String body = response.bodyText(); 147 | 148 | assertEquals( 149 | "Wikipedia in\n" + 150 | "\n" + 151 | "chunks.", body.replace("\r\n", "\n")); 152 | 153 | assertEquals("TheData", response.header("SomeAfterHeader")); 154 | } 155 | 156 | 157 | } 158 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/RemoveHeaderTest.java: -------------------------------------------------------------------------------- 1 | package jodd.http; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.IOException; 7 | 8 | import static org.junit.jupiter.api.Assertions.assertFalse; 9 | import static org.junit.jupiter.api.Assertions.assertNotNull; 10 | import static org.junit.jupiter.api.Assertions.assertNull; 11 | 12 | class RemoveHeaderTest { 13 | 14 | @Test 15 | void testRemoveHeader() { 16 | HttpRequest request = HttpRequest 17 | .get("https://example.com") 18 | .header("x-dummy-header", "remove me"); 19 | 20 | assertNotNull(request.header("x-dummy-header")); 21 | 22 | request.headerRemove("x-dummy-header"); 23 | 24 | assertNull(request.header("x-dummy-header")); 25 | } 26 | 27 | @Test 28 | void testRemoveHeaderUserAgent() throws IOException { 29 | HttpBase.Defaults.headers.remove("User-Agent"); 30 | 31 | HttpRequest request = HttpRequest 32 | .get("https://example.com") 33 | .header("x-dummy-header", "remove me"); 34 | 35 | assertNull(request.header("User-Agent")); 36 | 37 | request.headerRemove("User-Agent"); 38 | 39 | assertNull(request.header("User-Agent")); 40 | 41 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 42 | request.sendTo(baos); 43 | String out = baos.toString(); 44 | 45 | assertFalse(out.contains("User-Agent")); 46 | 47 | HttpBase.Defaults.headers.addHeader("User-Agent", "Jodd HTTP"); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/TestServer.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import jodd.io.FileUtil; 29 | 30 | import java.io.File; 31 | import java.net.URL; 32 | 33 | 34 | /** 35 | * Common server content. 36 | */ 37 | public abstract class TestServer { 38 | 39 | protected File webRoot; 40 | 41 | public void start() throws Exception { 42 | webRoot = FileUtil.createTempDirectory("jodd-http", "test"); 43 | webRoot.deleteOnExit(); 44 | 45 | // web-inf 46 | 47 | File webInfFolder = new File(webRoot, "WEB-INF"); 48 | webInfFolder.mkdir(); 49 | 50 | // web.xml 51 | 52 | URL webXmlUrl = TestServer.class.getResource("web.xml"); 53 | File webXmlFile = FileUtil.toFile(webXmlUrl); 54 | 55 | FileUtil.copy(webXmlFile, webInfFolder); 56 | 57 | // lib folder 58 | 59 | File libFolder = new File(webInfFolder, "lib"); 60 | libFolder.mkdir(); 61 | 62 | // classes 63 | 64 | File classes = new File(webInfFolder, "classes/jodd/http/fixture"); 65 | classes.mkdirs(); 66 | 67 | URL echoServletUrl = TestServer.class.getResource("fixture/EchoServlet.class"); 68 | File echoServletFile = FileUtil.toFile(echoServletUrl); 69 | FileUtil.copyFileToDir(echoServletFile, classes); 70 | 71 | echoServletUrl = TestServer.class.getResource("fixture/Echo2Servlet.class"); 72 | echoServletFile = FileUtil.toFile(echoServletUrl); 73 | FileUtil.copyFileToDir(echoServletFile, classes); 74 | 75 | echoServletUrl = TestServer.class.getResource("fixture/Echo3Servlet.class"); 76 | echoServletFile = FileUtil.toFile(echoServletUrl); 77 | FileUtil.copyFileToDir(echoServletFile, classes); 78 | 79 | URL redirectServletUrl = TestServer.class.getResource("fixture/RedirectServlet.class"); 80 | File redirectServletFile = FileUtil.toFile(redirectServletUrl); 81 | FileUtil.copyFileToDir(redirectServletFile, classes); 82 | 83 | URL targetServletUrl = TestServer.class.getResource("fixture/TargetServlet.class"); 84 | File targetServletFile = FileUtil.toFile(targetServletUrl); 85 | FileUtil.copyFileToDir(targetServletFile, classes); 86 | } 87 | 88 | public void stop() throws Exception { 89 | webRoot.delete(); 90 | } 91 | } -------------------------------------------------------------------------------- /src/test/java/jodd/http/TimeoutTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import org.junit.jupiter.api.AfterAll; 29 | import org.junit.jupiter.api.BeforeAll; 30 | import org.junit.jupiter.api.Test; 31 | 32 | import static org.junit.jupiter.api.Assertions.assertEquals; 33 | import static org.junit.jupiter.api.Assertions.fail; 34 | 35 | class TimeoutTest { 36 | 37 | static TestServer testServer; 38 | 39 | @BeforeAll 40 | static void startServer() throws Exception { 41 | testServer = new TomcatServer(); 42 | testServer.start(); 43 | } 44 | 45 | @AfterAll 46 | static void stopServer() throws Exception { 47 | testServer.stop(); 48 | } 49 | 50 | @Test 51 | void testTimeout() { 52 | HttpRequest httpRequest = HttpRequest.get("localhost:8173/slow"); 53 | httpRequest.timeout(1000); 54 | 55 | try { 56 | httpRequest.send(); 57 | fail("error"); 58 | } 59 | catch(HttpException ignore) { 60 | } 61 | 62 | httpRequest = HttpRequest.get("localhost:8173/slow"); 63 | httpRequest.timeout(6000); 64 | 65 | int status = httpRequest.send().statusCode(); 66 | 67 | assertEquals(200, status); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/TomcatServer.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http; 27 | 28 | import org.apache.catalina.startup.Tomcat; 29 | 30 | /** 31 | * Tomcat Server. 32 | */ 33 | public class TomcatServer extends TestServer { 34 | 35 | protected Tomcat tomcat; 36 | 37 | @Override 38 | public void start() throws Exception { 39 | super.start(); 40 | 41 | String workingDir = System.getProperty("java.io.tmpdir"); 42 | 43 | tomcat = new Tomcat(); 44 | tomcat.setPort(8173); 45 | tomcat.setBaseDir(workingDir); 46 | tomcat.addWebapp("", webRoot.getAbsolutePath()); 47 | 48 | tomcat.start(); 49 | } 50 | 51 | @Override 52 | public void stop() throws Exception { 53 | tomcat.stop(); 54 | tomcat.destroy(); 55 | super.stop(); 56 | } 57 | } -------------------------------------------------------------------------------- /src/test/java/jodd/http/fixture/Data.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.fixture; 27 | 28 | import javax.servlet.http.Cookie; 29 | import java.util.Map; 30 | 31 | public class Data { 32 | 33 | public static Data ref; 34 | 35 | public boolean get; 36 | public boolean post; 37 | public String queryString; 38 | public String body; 39 | public Map header; 40 | public Map params; 41 | public Map parts; 42 | public Map fileNames; 43 | public Cookie[] cookies; 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/fixture/Echo2Servlet.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.fixture; 27 | 28 | import javax.servlet.annotation.MultipartConfig; 29 | import javax.servlet.http.HttpServletRequest; 30 | import java.io.IOException; 31 | import java.nio.charset.StandardCharsets; 32 | 33 | @MultipartConfig 34 | public class Echo2Servlet extends EchoServlet { 35 | 36 | @Override 37 | protected void readAll(final HttpServletRequest req) throws IOException { 38 | Data.ref.queryString = req.getQueryString(); 39 | Data.ref.header = copyHeaders(req); 40 | Data.ref.params = copyParams(req, StandardCharsets.UTF_8.name()); 41 | Data.ref.parts = copyParts(req); 42 | Data.ref.fileNames = copyFileName(req); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/fixture/Echo3Servlet.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.fixture; 27 | 28 | import javax.servlet.annotation.MultipartConfig; 29 | import javax.servlet.http.HttpServletRequest; 30 | import java.nio.charset.StandardCharsets; 31 | 32 | @MultipartConfig 33 | public class Echo3Servlet extends EchoServlet { 34 | 35 | @Override 36 | protected void readAll(final HttpServletRequest req) { 37 | Data.ref.queryString = req.getQueryString(); 38 | Data.ref.header = copyHeaders(req); 39 | Data.ref.params = copyParams(req, StandardCharsets.ISO_8859_1.name()); 40 | Data.ref.parts = copyParts(req); 41 | Data.ref.fileNames = copyFileName(req); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/fixture/EchoServlet.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.fixture; 27 | 28 | import jodd.io.IOUtil; 29 | import jodd.util.StringUtil; 30 | import org.apache.catalina.core.ApplicationPart; 31 | 32 | import javax.servlet.ServletException; 33 | import javax.servlet.http.Cookie; 34 | import javax.servlet.http.HttpServlet; 35 | import javax.servlet.http.HttpServletRequest; 36 | import javax.servlet.http.HttpServletResponse; 37 | import javax.servlet.http.Part; 38 | import java.io.BufferedReader; 39 | import java.io.IOException; 40 | import java.io.StringWriter; 41 | import java.nio.charset.Charset; 42 | import java.nio.charset.StandardCharsets; 43 | import java.util.Collection; 44 | import java.util.Enumeration; 45 | import java.util.HashMap; 46 | import java.util.Map; 47 | 48 | public class EchoServlet extends HttpServlet { 49 | 50 | @Override 51 | protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { 52 | Data.ref = new Data(); 53 | Data.ref.get = true; 54 | Data.ref.post = false; 55 | readAll(req); 56 | 57 | if (Data.ref.cookies != null) { 58 | for (final Cookie cookie : Data.ref.cookies) { 59 | cookie.setValue(cookie.getValue() + "!"); 60 | resp.addCookie(cookie); 61 | } 62 | } 63 | 64 | write(resp, Data.ref.body); 65 | } 66 | 67 | @Override 68 | protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { 69 | Data.ref = new Data(); 70 | Data.ref.post = true; 71 | Data.ref.get = false; 72 | readAll(req); 73 | write(resp, Data.ref.body); 74 | } 75 | 76 | // ---------------------------------------------------------------- write 77 | 78 | protected void write(final HttpServletResponse resp, final String text) throws IOException { 79 | if (text != null) { 80 | resp.setContentLength(text.getBytes(StandardCharsets.UTF_8).length); 81 | resp.setContentType("text/html;charset=UTF-8"); 82 | resp.getWriter().write(text); 83 | resp.flushBuffer(); 84 | } 85 | } 86 | 87 | // ---------------------------------------------------------------- read all 88 | 89 | protected void readAll(final HttpServletRequest req) throws IOException { 90 | Data.ref.body = readRequestBody(req); 91 | Data.ref.queryString = req.getQueryString(); 92 | Data.ref.header = copyHeaders(req); 93 | Data.ref.cookies = req.getCookies(); 94 | } 95 | 96 | protected String readRequestBody(final HttpServletRequest request) throws IOException { 97 | final BufferedReader buff = request.getReader(); 98 | final StringWriter out = new StringWriter(); 99 | IOUtil.copy(buff, out); 100 | return out.toString(); 101 | } 102 | 103 | protected Map copyHeaders(final HttpServletRequest req) { 104 | final Enumeration enumeration = req.getHeaderNames(); 105 | final Map header = new HashMap<>(); 106 | 107 | while (enumeration.hasMoreElements()) { 108 | final String name = enumeration.nextElement().toString(); 109 | final String value = req.getHeader(name); 110 | header.put(name, value); 111 | } 112 | 113 | return header; 114 | } 115 | 116 | protected Map copyParams(final HttpServletRequest req, final String fromEncoding) { 117 | final String charset = req.getParameter("enc"); 118 | 119 | final Enumeration enumeration = req.getParameterNames(); 120 | final Map params = new HashMap<>(); 121 | 122 | while (enumeration.hasMoreElements()) { 123 | final String name = enumeration.nextElement().toString(); 124 | String value = req.getParameter(name); 125 | if (charset != null) { 126 | value = StringUtil.convertCharset(value, Charset.forName(fromEncoding), Charset.forName(charset)); 127 | } 128 | params.put(name, value); 129 | } 130 | 131 | return params; 132 | } 133 | 134 | protected Map copyParts(final HttpServletRequest req) { 135 | final Map parts = new HashMap<>(); 136 | if (req.getContentType() == null) { 137 | return parts; 138 | } 139 | if (req.getContentType() != null && !req.getContentType().toLowerCase().contains("multipart/form-data")) { 140 | return parts; 141 | } 142 | 143 | final String enc = "UTF-8"; 144 | 145 | try { 146 | final Collection prs = req.getParts(); 147 | 148 | for (final Part p : prs) { 149 | parts.put(p.getName(), new String(IOUtil.readBytes(p.getInputStream()), enc)); 150 | } 151 | } 152 | catch (final IOException | ServletException e) { 153 | e.printStackTrace(); 154 | } 155 | 156 | return parts; 157 | } 158 | 159 | protected Map copyFileName(final HttpServletRequest req) { 160 | final Map parts = new HashMap<>(); 161 | if (req.getContentType() == null) { 162 | return parts; 163 | } 164 | if (req.getContentType() != null && !req.getContentType().toLowerCase().contains("multipart/form-data")) { 165 | return parts; 166 | } 167 | 168 | try { 169 | final Collection prs = req.getParts(); 170 | 171 | for (final Part p : prs) { 172 | if (p instanceof ApplicationPart) { 173 | final ApplicationPart ap = (ApplicationPart) p; 174 | parts.put(p.getName(), ap.getSubmittedFileName()); 175 | } 176 | } 177 | } 178 | catch (final IOException | ServletException e) { 179 | e.printStackTrace(); 180 | } 181 | 182 | return parts; 183 | } 184 | 185 | } 186 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/fixture/RedirectServlet.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.fixture; 27 | 28 | import javax.servlet.ServletException; 29 | import javax.servlet.http.HttpServlet; 30 | import javax.servlet.http.HttpServletRequest; 31 | import javax.servlet.http.HttpServletResponse; 32 | import java.io.IOException; 33 | 34 | /** 35 | * Simply redirects to '/target'. 36 | */ 37 | public class RedirectServlet extends HttpServlet { 38 | 39 | @Override 40 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) 41 | throws ServletException, IOException { 42 | 43 | resp.sendRedirect("/target"); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/java/jodd/http/fixture/SlowServlet.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.fixture; 27 | 28 | import jodd.util.ThreadUtil; 29 | 30 | import javax.servlet.ServletException; 31 | import javax.servlet.http.HttpServlet; 32 | import javax.servlet.http.HttpServletRequest; 33 | import javax.servlet.http.HttpServletResponse; 34 | import java.io.IOException; 35 | import java.nio.charset.StandardCharsets; 36 | 37 | public class SlowServlet extends HttpServlet { 38 | 39 | @Override 40 | protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { 41 | ThreadUtil.sleep(5000); 42 | write(resp, "OK"); 43 | } 44 | 45 | protected void write(final HttpServletResponse resp, final String text) throws IOException { 46 | if (text != null) { 47 | resp.setContentLength(text.getBytes(StandardCharsets.UTF_8.name()).length); 48 | resp.setContentType("text/html;charset=UTF-8"); 49 | resp.getWriter().write(text); 50 | resp.flushBuffer(); 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/fixture/StringHttpRequest.java: -------------------------------------------------------------------------------- 1 | package jodd.http.fixture; 2 | 3 | import jodd.http.HttpConnection; 4 | import jodd.http.HttpConnectionProvider; 5 | import jodd.http.HttpRequest; 6 | import jodd.http.ProxyInfo; 7 | 8 | import java.io.ByteArrayInputStream; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.InputStream; 11 | import java.io.OutputStream; 12 | 13 | public class StringHttpRequest { 14 | 15 | public static HttpRequest create(final String payload) { 16 | return new HttpRequest().withConnectionProvider(new HttpConnectionProvider() { 17 | @Override 18 | public void useProxy(ProxyInfo proxyInfo) { 19 | } 20 | 21 | @Override 22 | public HttpConnection createHttpConnection(HttpRequest httpRequest) { 23 | return new HttpConnection() { 24 | 25 | private final ByteArrayInputStream in = new ByteArrayInputStream(payload.getBytes()); 26 | private final ByteArrayOutputStream out = new ByteArrayOutputStream(1024); 27 | 28 | @Override 29 | public void init() { 30 | } 31 | 32 | @Override 33 | public OutputStream getOutputStream() { 34 | return out; 35 | } 36 | 37 | @Override 38 | public InputStream getInputStream() { 39 | return in; 40 | } 41 | 42 | @Override 43 | public void close() { 44 | } 45 | 46 | @Override 47 | public void setTimeout(int milliseconds) { 48 | } 49 | }; 50 | } 51 | }); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/jodd/http/fixture/TargetServlet.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2003-present, Jodd Team (http://jodd.org) 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | // POSSIBILITY OF SUCH DAMAGE. 25 | 26 | package jodd.http.fixture; 27 | 28 | import javax.servlet.ServletException; 29 | import javax.servlet.http.HttpServlet; 30 | import javax.servlet.http.HttpServletRequest; 31 | import javax.servlet.http.HttpServletResponse; 32 | import java.io.IOException; 33 | 34 | public class TargetServlet extends HttpServlet { 35 | 36 | @Override 37 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) 38 | throws ServletException, IOException { 39 | 40 | resp.getWriter().write("target!"); 41 | } 42 | 43 | 44 | } -------------------------------------------------------------------------------- /src/test/resources/jodd/http/1-response.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Date: Sat, 23 Mar 2013 23:34:18 GMT 3 | Cache-Control: max-age=0, must-revalidate, no-cache, no-store, private, post-check=0, pre-check=0 4 | Pragma: no-cache 5 | Expires: Thu, 01 Jan 1970 00:00:00 GMT 6 | Content-Type: text/html;charset=UTF-8 7 | Connection: close 8 | Content-Length: 102 9 | 10 | 11 | 12 | 13 | This is UTF8 Encoding. 14 | Тхис ис УТФ8 Енцодинг. 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test/resources/jodd/http/2-response.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json; charset=UTF-8 3 | Date: Thu, 27 Feb 2014 21:10:55 GMT 4 | Expires: Fri, 28 Feb 2014 21:10:55 GMT 5 | Cache-Control: public, max-age=86400 6 | Vary: Accept-Language 7 | Access-Control-Allow-Origin: * 8 | Server: mafe 9 | X-Xss-Protection: 1; mode=block 10 | X-Frame-Options: SAMEORIGIN 11 | Alternate-Protocol: 80:quic 12 | Connection: close -------------------------------------------------------------------------------- /src/test/resources/jodd/http/3-response.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json; charset=UTF-8 3 | Date: Thu, 27 Feb 2014 21:10:55 GMT 4 | Expires: Fri, 28 Feb 2014 21:10:55 GMT 5 | Cache-Control: public, max-age=86400 6 | Vary: Accept-Language 7 | Access-Control-Allow-Origin: * 8 | Server: mafe 9 | X-Xss-Protection: 1; mode=block 10 | X-Frame-Options: SAMEORIGIN 11 | Alternate-Protocol: 80:quic 12 | Connection: close 13 | 14 | Body! -------------------------------------------------------------------------------- /src/test/resources/jodd/http/4-response.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | content-type:text/html; charset=utf-8 3 | Transfer-Encoding: chunked 4 | Connection: close 5 | 6 | 4 7 | Wiki 8 | 5 9 | pedia 10 | e 11 | in 12 | 13 | chunks. 14 | 0 15 | -------------------------------------------------------------------------------- /src/test/resources/jodd/http/5-response.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | content-type:text/html; charset=utf-8 3 | Transfer-Encoding: chunked 4 | Connection: close 5 | 6 | 4 7 | Wiki 8 | 5 9 | pedia 10 | e 11 | in 12 | 13 | chunks. 14 | 0 15 | SomeAfterHeader: TheData 16 | -------------------------------------------------------------------------------- /src/test/resources/jodd/http/6-response.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 2 | content-type:text/html; charset=utf-8 3 | Content-Length: 102 4 | Transfer-Encoding: chunked 5 | Connection: close 6 | 7 | 4 8 | Wiki 9 | 5 10 | pedia 11 | e 12 | in 13 | 14 | chunks. 15 | 0 16 | SomeAfterHeader: TheData 17 | -------------------------------------------------------------------------------- /src/test/resources/jodd/http/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | EchoServlet 9 | EchoServlet 10 | jodd.http.fixture.EchoServlet 11 | 12 | 13 | 14 | EchoServlet 15 | /echo 16 | 17 | 18 | 19 | Echo2Servlet 20 | Echo2Servlet 21 | jodd.http.fixture.Echo2Servlet 22 | 23 | 24 | 25 | Echo2Servlet 26 | /echo2 27 | 28 | 29 | 30 | Echo3Servlet 31 | Echo3Servlet 32 | jodd.http.fixture.Echo3Servlet 33 | 34 | 35 | 36 | Echo3Servlet 37 | /echo3 38 | 39 | 40 | 41 | TargetServlet 42 | TargetServlet 43 | jodd.http.fixture.TargetServlet 44 | 45 | 46 | 47 | TargetServlet 48 | /target 49 | 50 | 51 | 52 | RedirectServlet 53 | RedirectServlet 54 | jodd.http.fixture.RedirectServlet 55 | 56 | 57 | 58 | RedirectServlet 59 | /redirect 60 | 61 | 62 | 63 | SlowServlet 64 | SlowServlet 65 | jodd.http.fixture.SlowServlet 66 | 67 | 68 | 69 | SlowServlet 70 | /slow 71 | 72 | 73 | --------------------------------------------------------------------------------