Simplified Http

This is a fully featured http client for Scala which wraps java.net.HttpURLConnection

Features:

  • Zero dependencies
  • Cross compiled for Scala 2.10, 2.11, 2.12, and 2.13-M3
  • OAuth v1 request signing
  • Automatic support of gzip and deflate encodings from server
  • Easy to add querystring or form params. URL encoding is handled for you.
  • Multipart file uploads

Non-Features:

  • Async execution

    • The library is thread safe. HttpRequest and HttpResponse are immutable. So it should be easy to wrap in an execution framework of your choice.

Works in Google AppEngine and Android environments.

Note: 2.x.x is a new major version which is both syntactically and behaviorally different than the 0.x.x version.

Previous version is branched here: https://github.com/scalaj/scalaj-http/tree/0.3.x

Big differences:

  • Executing the request always returns a HttpResponse[T] instance that contains the response-code, headers, and body
  • Exceptions are no longer thrown for 4xx and 5xx response codes. Yay!
  • Http(url) is the starting point for every type of request (post, get, multi, etc)
  • You can easily create your own singleton instance to set your own defaults (timeouts, proxies, etc)
  • Sends "Accept-Encoding: gzip,deflate" request header and decompresses based on Content-Encoding (configurable)
  • Redirects are no longer followed by default. Use .option(HttpOptions.followRedirects(true)) to change.

Installation

in your build.sbt

libraryDependencies +=  "org.scalaj" %% "scalaj-http" % "2.4.1"

  

maven

<dependency>
<groupId>org.scalaj</groupId>
<artifactId>scalaj-http_${scala.version}</artifactId>
<version>2.4.1</version>
</dependency>

  

If you're including this in some other public library. Do your users a favor and change the fully qualified name so they don't have version conflicts if they're using a different version of this library. The easiest way to do that is just to copy the source into your project :)

Usage

Simple Get

import scalaj.http._

val response: HttpResponse[String] = Http("http://foo.com/search").param("q","monkeys").asString
response.body
response.code
response.headers
response.cookies

Immutable Request

Http(url) is just shorthand for a Http.apply which returns an immutable instance of HttpRequest.
You can create a HttpRequest and reuse it:

val request: HttpRequest = Http("http://date.jsontest.com/")

val responseOne = request.asString
val responseTwo = request.asString

Additive Request

All the "modification" methods of a HttpRequest are actually returning a new instance. The param(s), option(s), header(s) methods always add to their respective sets. So calling .headers(newHeaders) will return a HttpRequest instance that has newHeaders appended to the previous req.headers

Simple form encoded POST

Http("http://foo.com/add").postForm(Seq("name" -> "jon", "age" -> "29")).asString

OAuth v1 Dance and Request

Note: the .oauth(...) call must be the last method called in the request construction

import scalaj.http.{Http, Token}

val consumer = Token("key", "secret")
val response = Http("https://api.twitter.com/oauth/request_token").postForm(Seq("oauth_callback" -> "oob"))
.oauth(consumer).asToken println("Go to https://api.twitter.com/oauth/authorize?oauth_token=" + response.body.key) val verifier = Console.readLine("Enter verifier: ").trim val accessToken = Http("https://api.twitter.com/oauth/access_token").postForm.
.oauth(consumer, response.body, verifier).asToken println(Http("https://api.twitter.com/1.1/account/settings.json").oauth(consumer, accessToken.body).asString)

Parsing the response

Http("http://foo.com").{asString, asBytes, asParams}

Those methods will return an HttpResponse[String | Array[Byte] | Seq[(String, String)]] respectively

Advanced Usage Examples

Parse the response InputStream directly

val response: HttpResponse[Map[String,String]] = Http("http://foo.com").execute(parser = {inputStream =>
Json.parse[Map[String,String]](inputStream)
})

Post raw Array[Byte] or String data and get response code

Http(url).postData(data).header("content-type", "application/json").asString.code

Post multipart/form-data

Http(url).postMulti(MultiPart("photo", "headshot.png", "image/png", fileBytes)).asString

You can also stream uploads and get a callback on progress:

Http(url).postMulti(MultiPart("photo", "headshot.png", "image/png", inputStream, bytesInStream,
lenWritten => {
println(s"Wrote $lenWritten bytes out of $bytesInStream total for headshot.png")
})).asString

Stream a chunked transfer response (like an event stream)

Http("http://httpbin.org/stream/20").execute(is => {
scala.io.Source.fromInputStream(is).getLines().foreach(println)
})

note that you may have to wrap in a while loop and set a long readTimeout to stay connected

Send https request to site with self-signed or otherwise shady certificate

Http("https://localhost/").option(HttpOptions.allowUnsafeSSL).asString

Do a HEAD request

Http(url).method("HEAD").asString

Custom connect and read timeouts

These are set to 1000 and 5000 milliseconds respectively by default

Http(url).timeout(connTimeoutMs = 1000, readTimeoutMs = 5000).asString

Get request via a proxy

val response = Http(url).proxy(proxyHost, proxyPort).asString

Other custom options

The .option() method takes a function of type HttpURLConnection => Unit so you can manipulate the connection in whatever way you want before the request executes.

Change the Charset

By default, the charset for all param encoding and string response parsing is UTF-8. You can override with charset of your choice:

Http(url).charset("ISO-8859-1").asString

Create your own HttpRequest builder

You don't have to use the default Http singleton. Create your own:

object MyHttp extends BaseHttp (
proxyConfig = None,
options = HttpConstants.defaultOptions,
charset = HttpConstants.utf8,
sendBufferSize = 4096,
userAgent = "scalaj-http/1.0",
compress = true
)

Full API documentation

scaladocs here

Dealing with annoying java library issues

Overriding the Access-Control, Content-Length, Content-Transfer-Encoding, Host, Keep-Alive, Origin, Trailer, Transfer-Encoding, Upgrade, Via headers

Some of the headers are locked by the java library for "security" reasons and the behavior is that the library will just silently fail to set them. You can workaround by doing one of the following:

  • Start your JVM with this command line parameter: -Dsun.net.http.allowRestrictedHeaders=true
  • or, do this first thing at runtime: System.setProperty("sun.net.http.allowRestrictedHeaders", "true")

以上官方说明,下面具体怎么使用:

首先Http请求,返回json类型数据,就要有json解析及转化工具。

Scala sbt引入scalaj-http及spray-json.

"org.scalaj" % "scalaj-http_2.12" % "2.3.0",
"com.github.wangzaixiang" %% "spray-json" % "1.3.4",
"com.google.code.gson" % "gson" % "2.7"

  

工具类如下:

package test.scalajhttp

import com.google.gson.Gson
import scalaj.http.{Http, HttpOptions, HttpResponse}
import spray.json.DefaultJsonProtocol._
import spray.json.{JsValue, _} /**
* 类功能描述:Scalaj http 工具类
*
* @author WangXueXing create at 19-8-15 下午5:56
* @version 1.0.0
*/
object ScalajHttpUtil {
/**
* 成功
*/
val STATUS_SUCCESS: String = "success"
/**
* 失败
*/
val STATUS_FAIL: String = "fail" /**
* http公共请求类
*
* @param url Http路径如:https://www.baidu.com
* @param params 参数
* @return
*/
def requestUrl(url: String, params: Map[String, String]) = {
val httpRequest = Http(url)
.header("Content-Type", "application/xml")//"application/json"
.header("Charset", "UTF-8")
.option(HttpOptions.readTimeout(10000))
val response: HttpResponse[String] = (params != null && !params.isEmpty) match {
case true => httpRequest.params(params).asString
case false => httpRequest.asString
} response.body
} /**
* http公共请求类
*
* @param url Http路径如:https://www.baidu.com
* @param requestJson Json参数
* @return
*/
def postRequestUrl(url: String, requestJson: String) = {
val httpRequest = Http(url)
.header("Content-Type", "application/xml")//"application/json"
.header("Charset", "UTF-8")
.option(HttpOptions.readTimeout(10000))
val response: HttpResponse[String] = (requestJson != null && !requestJson.isEmpty) match {
case true => httpRequest.postData(requestJson).asString
case false => httpRequest.asString
} response.body
} /**
* 将object映射json string
*
* @param obj
* @return
*/
def objToJson(obj: NcRespose): String = {
new Gson().toJson(obj)
} /**
* 将map数据映射到Object
*
* @param jsonStr
* @return
*/
def jsonToObject(jsonStr: String): NcRespose = {
val jsonObj = jsonStr.parseJson.convertTo[Map[String, JsValue]]
mapToObject(jsonObj)
} /**
* 将map数据映射到PRackType类上
*
* @param jsonMap
* @return
*/
def mapToJson(jsonMap: Map[String, JsValue]): String = {
val obj = mapToObject(jsonMap)
new Gson().toJson(obj)
} /**
* 将map数据映射到Object
*
* @param jsonObj
* @return
*/
def mapToObject(jsonObj: Map[String, JsValue]): NcRespose = {
NcRespose(
status = toStringValue(jsonObj.get("status").get),
message = toStringValue(jsonObj.get("message").get)
)
} def toStringValue(jsValue: JsValue): String = {
s"$jsValue".replace("\"", "")
} def toIntValue(jsValue: JsValue): Int = {
s"$jsValue".replace("\"", "").toInt
} def toLongValue(jsValue: JsValue): Long = {
s"$jsValue".replace("\"", "").toLong
} def main(args: Array[String]): Unit = {
val jsonStr1 = "{\"billhead\":{\"bill_date\":\"2019-08-13\",\"creationtime\":\"2019-08-13 17:55:00\",\"creator\":\"1000\",\"local_money\":100,\"local_rate\":1,\"objecttype\":0,\"payway\":0,\"pk_currtype\":\"CNY\",\"pk_org\":\"101\",\"primal_money\":100},\"items\":[{\"billdetail_no\":0,\"pay_local\":100,\"pay_primal\":100,\"pk_oppaccount\":\"421860158018800081218\"}]}"
val jsonStr = postRequestUrl("http://10.100.99.98:8000/uapws/rest/SyncCMPPayBillRestful/add", jsonStr1) val gson = new Gson()
val respose = gson.fromJson(jsonStr, classOf[NcRespose]) // val respose = jsonToObject(jsonStr)
// println(jsonStr)
if(respose.status == STATUS_SUCCESS){
println(s"success: ${respose.message}")
} else {
println(s"fail: ${respose.message}")
}
}
}
case class NcRespose(status: String, message: String)

scala中使用json,比java中使用json复杂一些。尝试了json-smart;fast json; gson;json4s以及scala自带的json。

总结如下:

1. 普通json string 转化 object, 使用JSON.pareseFull 。

JSON.parseFull(str).get.asInstanceOf[Map[String, String]]("key") 

2. json 与 map 互相转化

val colors:Map[String,Object] = Map("red" -> "123456", "azure" -> "789789")
val json = JSONObject(colors)
println(json)
val jsonMap = JSON.parseFull(json.toString).get.asInstanceOf[Map[String,Object]]
println(jsonMap) 

3. json 与 class 互相转化

case class Student( name:String , no: String )

    val gson = new Gson
val student = Student("张三", "100")
val str = gson.toJson(student, classOf[Student])
println(str)
val student2 = gson.fromJson(str, classOf[Student])
println(student2)

尤其注意:使用 classOf ,不能使用 getclass

4. json与Map互相转化,需使用java的map

val map = new util.HashMap[String, Object]()
map.put("abc", List(s1,s2).toArray)
val gson = new Gson()
println( gson.toJson(map) )
另附,json判断代码 def isGoodJson(json: String):Boolean = { if(null == json) {
return false
}
val result = JSON.parseFull(json) match {
case Some(_: Map[String, Any]) => true
case None => false
case _ => false
}
result
}

请参考:

scalaj-http

Scala Http 请求调用 - scalaj-http的更多相关文章

  1. Post方式的Http流请求调用

    HttpRequest公共类: public static class HttpRequestAction { /// <summary> /// 发送http请求并返回响应 /// &l ...

  2. C# 使用 HttpPost 请求调用 WebService

    之前调用 WebService 都是直接添加服务引用,然后调用 WebService 方法的,最近发现还可以使用 Http 请求调用 WebService.这里还想说一句,还是 web api 的调用 ...

  3. ajax 请求调用问题

    http://localhost/dev/list 和  http://127.0.0.1/dev/list 最近在架构整体常规通用系统的解决方案,遭遇AJAX请求不执行的问题,刚开始以为Spring ...

  4. 请求通道在等待 00:00:58.9616639 以后答复时超时。增加传递给请求调用的超时值,或者增加绑定上的 SendTimeout 值。分配给此操作的时间可能是更长超时的一部分。

    异常信息:请求通道在等待 00:00:58.9616639 以后答复时超时.增加传递给请求调用的超时值,或者增加绑定上的 SendTimeout 值.分配给此操作的时间可能是更长超时的一部分. 开发背 ...

  5. C# 使用 HttpPost 请求调用 WebService (转)

    转自 https://www.cnblogs.com/Brambling/p/7266482.html 之前调用 WebService 都是直接添加服务引用,然后调用 WebService 方法的,最 ...

  6. .Net下的Http请求调用(Post与Get)

    http请求调用是开发中经常会用到的功能.在内,调用自有项目的Web Api等形式接口时会用到:在外,调用一些第三方功能接口时,也会用到,因为,这些第三方功能往往是通过http地址的形式提供的,比如: ...

  7. 使用Spring AsyncRestTemplate对象进行异步请求调用

    直接上代码: package com.mlxs.common.server.asyncrest; import org.apache.log4j.Logger; import org.springfr ...

  8. Spring框架下的 “接口调用、MVC请求” 调用参数、返回值、耗时信息输出

    主要拦截前端或后天的请求,打印请求方法参数.返回值.耗时.异常的日志.方便开发调试,能很快定位到问题出现在哪个方法中. 前端请求拦截,mvc的拦截器 import java.util.Date; im ...

  9. dubbo 请求调用过程分析

    服务消费方发起请求 当服务的消费方引用了某远程服务,服务的应用方在spring的配置实例如下: <dubbo:referenceid="demoService"interfa ...

随机推荐

  1. Centos7编译安装Nginx+keepalived

    一.安装环境.主机信息及软件版本 Nginx:1.12.2keepalived:2.0.12时间同步(同步后确认各服务器时间是否一致,不一致需要修改一下时区) 关闭防火墙 二.编译安装Nginx 1. ...

  2. Python 简单爬虫案例

    Python 简单爬虫案例 import requests url = "https://www.sogou.com/web" # 封装参数 wd = input('enter a ...

  3. TCP SYN flood洪水攻击原理和防御破解

    简介 TCP协议要经过三次握手才能建立连接: 于是出现了对于握手过程进行的攻击.攻击者发送大量的SYN包,服务器回应(SYN+ACK)包,但是攻击者不回应ACK包,这样的话,服务器不知道(SYN+AC ...

  4. Java生鲜电商平台-一次代码重构的实战案例

    Java生鲜电商平台-一次代码重构的实战案例 说明,Java开源生鲜电商平台-一次代码重构的实战案例,根据实际的例子,分析出重构与抽象,使代码更加的健壮与高效. 1.业务说明 系统原先已有登录功能,我 ...

  5. Linux下java验证码不显示:Could not initialize class sun.awt.X11FontManager

    一.问题 javaweb项目,登录的时候有个图片验证码的功能.在Windows本地测试能够正常显示,部署到Linux上就不行了.报错如下: org.springframework.web.util.N ...

  6. webpack4 css modules

    demo 代码点此,webpack4 中通过 css-loader 开启 css 模块化, 开始前先做点准备工作. 不了解 css 模块化的,可以前往查看github_css_modules. ##准 ...

  7. CTF必备技能丨Linux Pwn入门教程——利用漏洞获取libc

    Linux Pwn入门教程系列分享如约而至,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...

  8. openssl生成随机数

    #include <stdio.h> #include <openssl/bn.h> int main() { BIGNUM *bn; bn = BN_new(); //生成一 ...

  9. 高性能TcpServer(C#) - 4.文件通道(处理:文件分包,支持断点续传)

    高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...

  10. Android 项目主要文件

    1.manifests下的AndroidManifest.xml是Andriod程序的清单文件,该文件是整个项目的配置文件,Android四大组件Activity.BroadcastReceiver. ...