Using scalaj.http 2.4 I cannot get the correct code for a If-None-Match etag for this simple call:
import scalaj.http.Http
object EtagTest extends App {
val firstResponse = Http("https://api.github.com/users/octocat/orgs")
// get correct etag ...
val response = Http("https://api.github.com/users/octocat/orgs").header("If-None-Match", "\"98f0c1b396a4e5d54f4d5fe561d54b44\"").asString
println(response.code)
}
I'm expecting a 304 Not Modified but I get a 200.
I tried the following and it worked for me. It looks like the ETag you get with this program is not the ETag you've hard coded in your program. The strange thing is that when I send a cURL request to it, the ETag returned is the one you have hard coded.
import scalaj.http.Http
object ETagTest extends App {
val firstResponse = Http("https://api.github.com/users/octocat/orgs").asString
val response = Http("https://api.github.com/users/octocat/orgs").header("If-None-Match", firstResponse.header(key = "ETag").get).asString
println(response.code)
println(response.header(key = "ETag").get)
}
Output of the above:
304
"80b190627d4c87e9a37c34e20ea246a1"
Related
I am trying to do a GET request and print the JSON response that I get back. The JSON response should look like this.
{
"request_status": "Success",
"workflow_step": "End"
}
Here's my code:
handle(GetStatus) { args: GetStatus.Args =>
val client: Service[http.Request, http.Response] =
Http.client.withTlsWithoutValidation.newService("idm-preprod-fe1.twitter.biz:80")
val request = http.Request(
http.Method.Get,
"/plugin/rest/groupmanagement/getStatus/Create Group Request for mygroup (1638800484991)")
request.host = "idm-preprod-fe1.twitter.biz"
Future.value(GetStatusResponse(Option(client(request).toString)))
}
Now when my client sends the request to the server, I want to print the JSON but the format that I am getting is. Can someone please guide me as how to achieve this.
Promise#1589131174(state=Transforming(WaitQueue(size=1),Promise#1823443423(state=Transforming(WaitQueue(size=1),Promise#859399396(state=Transforming(WaitQueue(size=4),Promise#1441370332(state=Transforming(WaitQueue(size=2),Promise#1459834(state=Transforming(WaitQueue(size=2),Promise#156947070(state=Transforming(WaitQueue(size=1),Promise#1739595981(state=Transforming(WaitQueue(size=1),Promise#273198152(state=Transforming(WaitQueue(size=1),Promise#478329071(state=Transforming(WaitQueue(size=2),Promise#1175786031(state=Transforming(WaitQueue(size=1),Promise#1749285277(state=Transforming(WaitQueue(size=1),Promise#1733124454(state=Transforming(WaitQueue(size=1),Promise#1257379837(state=Transforming(WaitQueue(size=1),Promise#1192050340(state=Transforming(WaitQueue(size=1),Promise#1114225943(state=Transforming(WaitQueue(size=1),Promise#1417620904(state=Transforming(WaitQueue(size=1),Promise#1638767611(state=Interruptible(WaitQueue(size=2),<function1>))))))))))))))))))))))))))))))))))
client(request) is giving you a Future[http.Response]: it represents a response that will be available some time in the future.
You cannot use toString() on it directly because it's a Future and also because even if it was not a Future it would be a Response, which is a whole HTTP response, not only the body.
I'd recommend reading more about how Future works and how to use it.
In your case, you should do something like following (pseudo code as I'm not familiar with Twitter's Future):
client(request).map { httpResponse =>
val responseBody = httpResponse.body
GetStatusResponse(Option(responseBody))
}
So I was trying to follow this example:
Spring REST Docs: how to replace parameters
What I'm trying to do is to mask the JWT token in the header of my request and I have an OperationPreprocessor that looks like this:
import org.springframework.http.HttpHeaders
import org.springframework.restdocs.operation.OperationRequest
import org.springframework.restdocs.operation.OperationRequestFactory
import org.springframework.restdocs.operation.OperationResponse
import org.springframework.restdocs.operation.preprocess.OperationPreprocessor
class AuthHeaderPreprocessor implements OperationPreprocessor {
#Override
OperationRequest preprocess(OperationRequest request) {
HttpHeaders headers = new HttpHeaders()
headers.putAll(request.getHeaders())
headers.set('Authorization', 'Bearer 12345')
return new OperationRequestFactory().create(
request.getUri(),
request.getMethod(),
request.getContent(),
headers,
request.getParameters(),
request.getParts()
)
}
#Override
OperationResponse preprocess(OperationResponse response) {
return response
}
}
When I run the test they run without error but I don't see any change to the header. I'm using the OperationPreprocessor like this
RestAssuredRestDocumentation.document(
'event-list', preprocessRequest(new AuthHeaderPreprocessor()), ...
Any ideas what I may be missing.
The code I had actually worked and is a good example of how to filter headers. For some reason when testing it initially I wasn't working, but that seems like it was maybe just something cached in the build not getting cleared, as it works now.
I'd like to test that a Http4s Client is being called from my class ClassUnderTest (to make a HTTP request) and that the request made contains the headers I expect.
In 0.18.x, I did something like below. Using a side effect to store the value of the headers so that I can make an assertion after the call. In the example below, f.execute(...) is expected to make a PUT with the client instance and I'm trying to record all request handling and storing the headers.
"Request has headers" >> {
var headers = List[String]()
val client = Client[IO](new Kleisli[IO, Request[IO], DisposableResponse[IO]](request => {
headers = request.headers.map(_.name.toString()).toList
Ok().map(DisposableResponse(_, IO.pure(())))
}), IO.pure(()))
val f = ClassUnderTest(client)
f.execute("example")
headers must_== List(
"Content-Type",
"X-Forwarded-For",
"Content-Length"
)
}
The real code is here if you're interested.
ClassUnderTest took a Client[IO] so I could get the above working.
class ClassUnderTest(client: http4s.Client[IO])
In Http4s 0.20.12, I had to change the signature to:
class ClassUnderTest(client: Resource[IO, http4s.Client[IO]])
...and now I can't figure out how to stub out the client for tests. I experimented with JavaNetClientBuilder but that doesn't help because I can get an instance of Client (after .create) and now I need a Resource[IO, http4s.Client[IO]].
How can I use a test double to stand in for the Client / Resource[F, Client[F]] so that I can test the requests it makes?
The testing page on the docs doesn't really help me. I want a test double, not to test all the functionality of the Service (I don't want to startup a server).
I have looked at the dispatch tutorial, and can easily find how to get the header information (if the status is 200, if I have understood other posts) for instance with;
def main(args: Array[String]){
val svc = url("http://www.google.com")
val country = Http(svc OK as.String)
for (c <- country){
println(c)
}
}
However, I can not find how to get the response content. I would be thankful if someone could help me with that. I assume it should be a function applied on svc.
The documentation explains it:
The above defines and initiates a request to the given host where 2xx
responses are handled as a string. Since Dispatch is fully
asynchronous, country represents a future of the string rather than
the string itself.
(emphasis mine) where country refers to the request from your example and your example actually returns the body.
Note that your code example explicitely casts into String, but you can get the raw response object like this:
val svc = url("http://www.google.com")
val request = Http(svc)
val response = request()
print(s"Status\n ${response.getStatusCode}\nHeaders:\n ${response.getHeaders}\nBody:\n ${response.getResponseBody}")
This gets you the HTTP status code, all response headers and the entire response body.
See the entire reference for the Response here
How do I remove a cookie after processing the request and building the response?
I have tried the following code, but it does not seem to work:
get("/login") { request =>
val message = request.cookies.get("flash-message").map(_.value)
request.removeCookie("flash-message")
render.view(LoginView(message)).toFuture
}
I could not find any methods on ResponseBuilder that would remove a cookie, either.
It turns out, the way to do it, is the usual "JavaScript" way. Just create an expired cookie and send back, like this:
import com.twitter.finagle.http.Cookie
import com.twitter.util.Duration
import java.util.concurrent.TimeUnit
get("/login") { request =>
val message = request.cookies.get("flash-message").map(_.value)
val c = Cookie("flash-message", "")
c.maxAge = Duration(-10, TimeUnit.DAYS)
render.view(LoginView(message)).cookie(c).toFuture
}
Of course 10 days is just an arbitrary "duration" in the past.