Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wd1105040417
retrofit
提交
737b844b
R
retrofit
项目概览
wd1105040417
/
retrofit
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
retrofit
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
737b844b
编写于
4月 11, 2013
作者:
J
Jake Wharton
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Roll our own multi-part implementation.
Drop Apache mime4j dependency. Closes #141.
上级
2fcabb79
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
73 addition
and
81 deletion
+73
-81
pom.xml
pom.xml
+0
-6
retrofit/pom.xml
retrofit/pom.xml
+0
-4
retrofit/src/main/java/retrofit/http/MultipartTypedOutput.java
...fit/src/main/java/retrofit/http/MultipartTypedOutput.java
+54
-37
retrofit/src/test/java/retrofit/http/RequestBuilderTest.java
retrofit/src/test/java/retrofit/http/RequestBuilderTest.java
+18
-18
retrofit/src/test/java/retrofit/http/TestingUtils.java
retrofit/src/test/java/retrofit/http/TestingUtils.java
+0
-14
retrofit/src/test/java/retrofit/http/client/UrlConnectionClientTest.java
...st/java/retrofit/http/client/UrlConnectionClientTest.java
+1
-2
未找到文件。
pom.xml
浏览文件 @
737b844b
...
@@ -51,7 +51,6 @@
...
@@ -51,7 +51,6 @@
<android.version>
4.1.1.4
</android.version>
<android.version>
4.1.1.4
</android.version>
<android.platform>
16
</android.platform>
<android.platform>
16
</android.platform>
<gson.version>
2.2.2
</gson.version>
<gson.version>
2.2.2
</gson.version>
<httpmime.version>
4.2.3
</httpmime.version>
<javax.inject.version>
1
</javax.inject.version>
<javax.inject.version>
1
</javax.inject.version>
<!-- Test Dependencies -->
<!-- Test Dependencies -->
...
@@ -111,11 +110,6 @@
...
@@ -111,11 +110,6 @@
<artifactId>
gson
</artifactId>
<artifactId>
gson
</artifactId>
<version>
${gson.version}
</version>
<version>
${gson.version}
</version>
</dependency>
</dependency>
<dependency>
<groupId>
org.apache.httpcomponents
</groupId>
<artifactId>
httpmime
</artifactId>
<version>
${httpmime.version}
</version>
</dependency>
<dependency>
<dependency>
<groupId>
junit
</groupId>
<groupId>
junit
</groupId>
...
...
retrofit/pom.xml
浏览文件 @
737b844b
...
@@ -20,10 +20,6 @@
...
@@ -20,10 +20,6 @@
<groupId>
com.google.code.gson
</groupId>
<groupId>
com.google.code.gson
</groupId>
<artifactId>
gson
</artifactId>
<artifactId>
gson
</artifactId>
</dependency>
</dependency>
<dependency>
<groupId>
org.apache.httpcomponents
</groupId>
<artifactId>
httpmime
</artifactId>
</dependency>
<dependency>
<dependency>
<groupId>
com.google.android
</groupId>
<groupId>
com.google.android
</groupId>
<artifactId>
android
</artifactId>
<artifactId>
android
</artifactId>
...
...
retrofit/src/main/java/retrofit/http/MultipartTypedOutput.java
浏览文件 @
737b844b
...
@@ -3,64 +3,81 @@ package retrofit.http;
...
@@ -3,64 +3,81 @@ package retrofit.http;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.io.OutputStream
;
import
org.apache.http.entity.mime.MIME
;
import
java.util.LinkedHashMap
;
import
org.apache.http.entity.mime.MultipartEntity
;
import
java.util.Map
;
import
org.apache.http.entity.mime.content.AbstractContentBody
;
import
java.util.UUID
;
import
retrofit.http.mime.TypedFile
;
import
retrofit.http.mime.TypedOutput
;
import
retrofit.http.mime.TypedOutput
;
final
class
MultipartTypedOutput
implements
TypedOutput
{
final
class
MultipartTypedOutput
implements
TypedOutput
{
// TODO implement our own Multipart logic instead!
final
Map
<
String
,
TypedOutput
>
parts
=
new
LinkedHashMap
<
String
,
TypedOutput
>();
final
MultipartEntity
cheat
=
new
MultipartEntity
();
private
final
String
boundary
;
MultipartTypedOutput
()
{
boundary
=
UUID
.
randomUUID
().
toString
();
}
void
addPart
(
String
name
,
TypedOutput
body
)
{
void
addPart
(
String
name
,
TypedOutput
body
)
{
cheat
.
addPart
(
name
,
new
TypedOutputBody
(
body
));
if
(
name
==
null
)
{
throw
new
NullPointerException
(
"Part name must not be null."
);
}
if
(
body
==
null
)
{
throw
new
NullPointerException
(
"Part body must not be null."
);
}
parts
.
put
(
name
,
body
);
}
}
@Override
public
String
mimeType
()
{
@Override
public
String
mimeType
()
{
return
cheat
.
getContentType
().
getValue
()
;
return
"multipart/form-data; boundary="
+
boundary
;
}
}
@Override
public
long
length
()
{
@Override
public
long
length
()
{
return
cheat
.
getContentLength
()
;
return
-
1
;
}
}
@Override
public
void
writeTo
(
OutputStream
out
)
throws
IOException
{
@Override
public
void
writeTo
(
OutputStream
out
)
throws
IOException
{
cheat
.
writeTo
(
out
);
boolean
first
=
true
;
}
for
(
Map
.
Entry
<
String
,
TypedOutput
>
part
:
parts
.
entrySet
())
{
writeBoundary
(
out
,
boundary
,
first
,
false
);
/** Adapts {@link org.apache.http.entity.mime.content.ContentBody} to {@link TypedOutput}. */
writePart
(
out
,
part
);
static
class
TypedOutputBody
extends
AbstractContentBody
{
first
=
false
;
final
TypedOutput
typedBytes
;
TypedOutputBody
(
TypedOutput
typedBytes
)
{
super
(
typedBytes
.
mimeType
());
this
.
typedBytes
=
typedBytes
;
}
}
writeBoundary
(
out
,
boundary
,
false
,
true
);
}
@Override
public
long
getContentLength
()
{
private
static
void
writeBoundary
(
OutputStream
out
,
String
boundary
,
boolean
first
,
boolean
last
)
return
typedBytes
.
length
();
throws
IOException
{
StringBuilder
sb
=
new
StringBuilder
();
if
(!
first
)
{
sb
.
append
(
"\r\n"
);
}
}
sb
.
append
(
"--"
);
@Override
public
String
getFilename
()
{
sb
.
append
(
boundary
);
return
null
;
if
(
last
)
{
sb
.
append
(
"--"
);
}
else
{
sb
.
append
(
"\r\n"
);
}
}
out
.
write
(
sb
.
toString
().
getBytes
(
"UTF-8"
));
}
@Override
public
String
getCharset
()
{
private
static
void
writePart
(
OutputStream
out
,
Map
.
Entry
<
String
,
TypedOutput
>
part
)
return
null
;
throws
IOException
{
}
String
name
=
part
.
getKey
();
TypedOutput
value
=
part
.
getValue
();
@Override
public
String
getTransferEncoding
()
{
StringBuilder
headers
=
new
StringBuilder
();
return
MIME
.
ENC_BINARY
;
headers
.
append
(
"Content-Disposition: form-data; name=\""
);
headers
.
append
(
name
);
if
(
value
instanceof
TypedFile
)
{
headers
.
append
(
"; filename=\""
);
headers
.
append
(((
TypedFile
)
value
).
file
().
getName
());
}
}
headers
.
append
(
"\"\r\nContent-Type: "
);
headers
.
append
(
value
.
mimeType
());
headers
.
append
(
"\r\nContent-Transfer-Encoding: binary\r\n\r\n"
);
out
.
write
(
headers
.
toString
().
getBytes
(
"UTF-8"
));
@Override
public
void
writeTo
(
OutputStream
out
)
throws
IOException
{
value
.
writeTo
(
out
);
// Note: We probably want to differentiate I/O errors that occur while reading a file from
// network errors. Network operations can be retried. File operations will probably continue
// to fail.
//
// In the case of photo uploads, we at least check that the file exists before we even try to
// upload it.
typedBytes
.
writeTo
(
out
);
}
}
}
}
}
retrofit/src/test/java/retrofit/http/RequestBuilderTest.java
浏览文件 @
737b844b
...
@@ -8,10 +8,10 @@ import java.lang.reflect.Method;
...
@@ -8,10 +8,10 @@ import java.lang.reflect.Method;
import
java.net.URISyntaxException
;
import
java.net.URISyntaxException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.Set
;
import
org.apache.http.entity.mime.FormBodyPart
;
import
org.apache.http.entity.mime.HttpMultipart
;
import
org.junit.Test
;
import
org.junit.Test
;
import
retrofit.http.client.Request
;
import
retrofit.http.client.Request
;
import
retrofit.http.mime.TypedOutput
;
import
retrofit.http.mime.TypedOutput
;
...
@@ -20,7 +20,6 @@ import retrofit.http.mime.TypedString;
...
@@ -20,7 +20,6 @@ import retrofit.http.mime.TypedString;
import
static
org
.
fest
.
assertions
.
api
.
Assertions
.
assertThat
;
import
static
org
.
fest
.
assertions
.
api
.
Assertions
.
assertThat
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
static
retrofit
.
http
.
MultipartTypedOutput
.
TypedOutputBody
;
import
static
retrofit
.
http
.
RestMethodInfo
.
NO_SINGLE_ENTITY
;
import
static
retrofit
.
http
.
RestMethodInfo
.
NO_SINGLE_ENTITY
;
public
class
RequestBuilderTest
{
public
class
RequestBuilderTest
{
...
@@ -76,7 +75,7 @@ public class RequestBuilderTest {
...
@@ -76,7 +75,7 @@ public class RequestBuilderTest {
assertThat
(
request
.
getUrl
()).
isEqualTo
(
"http://example.com/foo/bar/pong/?kit=kat&riff=raff"
);
assertThat
(
request
.
getUrl
()).
isEqualTo
(
"http://example.com/foo/bar/pong/?kit=kat&riff=raff"
);
assertThat
(
request
.
getBody
()).
isNull
();
assertThat
(
request
.
getBody
()).
isNull
();
}
}
@Test
public
void
getWithPathAndQueryQuestionMarkParam
()
throws
Exception
{
@Test
public
void
getWithPathAndQueryQuestionMarkParam
()
throws
Exception
{
Request
request
=
new
Helper
()
//
Request
request
=
new
Helper
()
//
.
setMethod
(
"GET"
)
//
.
setMethod
(
"GET"
)
//
...
@@ -90,7 +89,7 @@ public class RequestBuilderTest {
...
@@ -90,7 +89,7 @@ public class RequestBuilderTest {
assertThat
(
request
.
getUrl
()).
isEqualTo
(
"http://example.com/foo/bar/pong%3F/?kit=kat%3F"
);
assertThat
(
request
.
getUrl
()).
isEqualTo
(
"http://example.com/foo/bar/pong%3F/?kit=kat%3F"
);
assertThat
(
request
.
getBody
()).
isNull
();
assertThat
(
request
.
getBody
()).
isNull
();
}
}
@Test
public
void
getWithPathAndQueryAmpersandParam
()
throws
Exception
{
@Test
public
void
getWithPathAndQueryAmpersandParam
()
throws
Exception
{
Request
request
=
new
Helper
()
//
Request
request
=
new
Helper
()
//
.
setMethod
(
"GET"
)
//
.
setMethod
(
"GET"
)
//
...
@@ -104,7 +103,7 @@ public class RequestBuilderTest {
...
@@ -104,7 +103,7 @@ public class RequestBuilderTest {
assertThat
(
request
.
getUrl
()).
isEqualTo
(
"http://example.com/foo/bar/pong%26/?kit=kat%26"
);
assertThat
(
request
.
getUrl
()).
isEqualTo
(
"http://example.com/foo/bar/pong%26/?kit=kat%26"
);
assertThat
(
request
.
getBody
()).
isNull
();
assertThat
(
request
.
getBody
()).
isNull
();
}
}
@Test
public
void
getWithPathAndQueryHashParam
()
throws
Exception
{
@Test
public
void
getWithPathAndQueryHashParam
()
throws
Exception
{
Request
request
=
new
Helper
()
//
Request
request
=
new
Helper
()
//
.
setMethod
(
"GET"
)
//
.
setMethod
(
"GET"
)
//
...
@@ -222,18 +221,18 @@ public class RequestBuilderTest {
...
@@ -222,18 +221,18 @@ public class RequestBuilderTest {
assertThat
(
request
.
getHeaders
()).
isEmpty
();
assertThat
(
request
.
getHeaders
()).
isEmpty
();
assertThat
(
request
.
getUrl
()).
isEqualTo
(
"http://example.com/foo/bar/"
);
assertThat
(
request
.
getUrl
()).
isEqualTo
(
"http://example.com/foo/bar/"
);
HttpMultipart
body
=
TestingUtils
.
extractEntity
(
request
.
getBody
());
MultipartTypedOutput
body
=
(
MultipartTypedOutput
)
request
.
getBody
();
assertThat
(
body
.
getBodyParts
()).
hasSize
(
2
);
assertThat
(
body
.
parts
).
hasSize
(
2
);
Iterator
<
Map
.
Entry
<
String
,
TypedOutput
>>
iterator
=
body
.
parts
.
entrySet
().
iterator
();
FormBodyPart
part1
=
(
FormBodyPart
)
body
.
getBodyParts
().
get
(
0
);
Map
.
Entry
<
String
,
TypedOutput
>
one
=
iterator
.
next
();
assertThat
(
part1
.
getName
()).
isEqualTo
(
"ping"
);
assertThat
(
one
.
getKey
()).
isEqualTo
(
"ping"
);
TypedOutputBody
body1
=
(
TypedOutputBody
)
part1
.
getBody
();
assertTypedBytes
(
one
.
getValue
(),
"pong"
);
assertTypedBytes
(
body1
.
typedBytes
,
"pong"
);
FormBodyPart
part2
=
(
FormBodyPart
)
body
.
getBodyParts
().
get
(
1
);
Map
.
Entry
<
String
,
TypedOutput
>
two
=
iterator
.
next
();
assertThat
(
part2
.
getName
()).
isEqualTo
(
"kit"
);
assertThat
(
two
.
getKey
()).
isEqualTo
(
"kit"
);
TypedOutputBody
body2
=
(
TypedOutputBody
)
part2
.
getBody
();
assertTypedBytes
(
two
.
getValue
(),
"kat"
);
assertTypedBytes
(
body2
.
typedBytes
,
"kat"
);
}
}
@Test
public
void
simpleHeaders
()
throws
Exception
{
@Test
public
void
simpleHeaders
()
throws
Exception
{
...
@@ -325,7 +324,8 @@ public class RequestBuilderTest {
...
@@ -325,7 +324,8 @@ public class RequestBuilderTest {
if
(
singleEntityArgumentIndex
!=
NO_SINGLE_ENTITY
)
{
if
(
singleEntityArgumentIndex
!=
NO_SINGLE_ENTITY
)
{
throw
new
IllegalStateException
(
"Single entity param already added."
);
throw
new
IllegalStateException
(
"Single entity param already added."
);
}
}
singleEntityArgumentIndex
=
namedParams
.
size
();
// Relying on the fact that this is already less one.
// Relying on the fact that this is already less one.
singleEntityArgumentIndex
=
namedParams
.
size
();
namedParams
.
add
(
null
);
namedParams
.
add
(
null
);
args
.
add
(
value
);
args
.
add
(
value
);
return
this
;
return
this
;
...
@@ -377,7 +377,7 @@ public class RequestBuilderTest {
...
@@ -377,7 +377,7 @@ public class RequestBuilderTest {
methodInfo
.
isMultipart
=
isMultipart
;
methodInfo
.
isMultipart
=
isMultipart
;
methodInfo
.
loaded
=
true
;
methodInfo
.
loaded
=
true
;
return
new
RequestBuilder
(
GSON
)
return
new
RequestBuilder
(
GSON
)
//
.
setApiUrl
(
url
)
.
setApiUrl
(
url
)
.
setHeaders
(
headers
)
.
setHeaders
(
headers
)
.
setArgs
(
args
.
toArray
(
new
Object
[
args
.
size
()]))
.
setArgs
(
args
.
toArray
(
new
Object
[
args
.
size
()]))
...
...
retrofit/src/test/java/retrofit/http/TestingUtils.java
浏览文件 @
737b844b
// Copyright 2013 Square, Inc.
// Copyright 2013 Square, Inc.
package
retrofit.http
;
package
retrofit.http
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Method
;
import
java.util.Map
;
import
java.util.Map
;
import
org.apache.http.entity.mime.HttpMultipart
;
import
org.apache.http.entity.mime.MultipartEntity
;
import
retrofit.http.mime.TypedOutput
;
import
retrofit.http.mime.TypedOutput
;
import
static
org
.
fest
.
assertions
.
api
.
Assertions
.
assertThat
;
import
static
org
.
fest
.
assertions
.
api
.
Assertions
.
assertThat
;
...
@@ -28,17 +25,6 @@ public abstract class TestingUtils {
...
@@ -28,17 +25,6 @@ public abstract class TestingUtils {
return
typedOutput
;
return
typedOutput
;
}
}
public
static
HttpMultipart
extractEntity
(
TypedOutput
output
)
throws
NoSuchFieldException
,
IllegalAccessException
{
if
(!(
output
instanceof
MultipartTypedOutput
))
{
throw
new
IllegalArgumentException
(
"TypedOutput was not a MultipartTypedOutput."
);
}
MultipartEntity
entity
=
((
MultipartTypedOutput
)
output
).
cheat
;
Field
httpMultipartField
=
MultipartEntity
.
class
.
getDeclaredField
(
"multipart"
);
httpMultipartField
.
setAccessible
(
true
);
return
(
HttpMultipart
)
httpMultipartField
.
get
(
entity
);
}
public
static
void
assertMultipart
(
TypedOutput
typedOutput
)
{
public
static
void
assertMultipart
(
TypedOutput
typedOutput
)
{
assertThat
(
typedOutput
).
isInstanceOf
(
MultipartTypedOutput
.
class
);
assertThat
(
typedOutput
).
isInstanceOf
(
MultipartTypedOutput
.
class
);
}
}
...
...
retrofit/src/test/java/retrofit/http/client/UrlConnectionClientTest.java
浏览文件 @
737b844b
...
@@ -66,9 +66,8 @@ public class UrlConnectionClientTest {
...
@@ -66,9 +66,8 @@ public class UrlConnectionClientTest {
assertThat
(
connection
.
getRequestMethod
()).
isEqualTo
(
"POST"
);
assertThat
(
connection
.
getRequestMethod
()).
isEqualTo
(
"POST"
);
assertThat
(
connection
.
getURL
().
toString
()).
isEqualTo
(
HOST
+
"/that/"
);
assertThat
(
connection
.
getURL
().
toString
()).
isEqualTo
(
HOST
+
"/that/"
);
assertThat
(
connection
.
getRequestProperties
()).
hasSize
(
2
);
assertThat
(
connection
.
getRequestProperties
()).
hasSize
(
1
);
assertThat
(
connection
.
getRequestProperty
(
"Content-Type"
)).
startsWith
(
"multipart/form-data;"
);
assertThat
(
connection
.
getRequestProperty
(
"Content-Type"
)).
startsWith
(
"multipart/form-data;"
);
assertThat
(
connection
.
getRequestProperty
(
"Content-Length"
)).
isNotNull
();
assertThat
(
connection
.
getOutputStream
().
toByteArray
().
length
).
isGreaterThan
(
0
);
assertThat
(
connection
.
getOutputStream
().
toByteArray
().
length
).
isGreaterThan
(
0
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录