C# WebClient.UploadData in Rails - ruby-on-rails

I have a c# method that I'm trying to convert to ruby on rails . I'm using unirest but I think something is not working correctly. This is my C# method :
private static string HTTPPoster(string url, string prmSendData)
{
try
{
WebClient wUpload = new WebClient();
wUpload.Proxy = null;
Byte[] bPostArray = Encoding.UTF8.GetBytes(prmSendData);
Byte[] bResponse = wUpload.UploadData(url, "POST", bPostArray);
Char[] sReturnChars = Encoding.UTF8.GetChars(bResponse);
string sWebPage = new string(sReturnChars);
return sWebPage;
}
catch
{
return "-1";
}
}
And This is what I tried so far in rails with unirest :
def HTTPPoster(url)
xml = "My XML Goes Here"
byte_array = xml.bytes
headers = {}
headers['Content-Type'] = "application/json"
headers['Accept'] = "application/json"
response = Unirest.post(url,
headers: headers,
parameters: {
body: byte_array
})
puts "response #{response.body}"
if ![200,201].include?(response.code)
raise "Mblox Error: #{response.code}, #{response.body}"
end
end
If you also know other libraries that can achieve what I need please let me know.

I used Faraday gem and sent the data as xml and not as byte array. And now I am achieving want I wanted.
response = Faraday.post(url) do |req|
req.headers['Content-Type'] = "application/xml"
req.headers['Accept'] = "*/*"
req.headers['Accept-Encoding'] = "gzip, deflate, br"
req.body = xml
end

Related

The view function did not return a valid response. The return type must be a string, dict

using Spotify API and Flask I am trying to extend refresh_token validity. As a result, when I send a request to the server, I get this error:
*The view function did not return a valid response. The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a Response.*
My code:
#app.route("/index")
def index():
if time.time() > session['expires_in']:
payload = session['refresh_token']
ref_payload = {
'grant_type': 'refresh_token',
'refresh_token':session["refresh_token"]
}
header={'Authorization': 'Basic ' + '<CLIENT_ID>:<CLIENT_SECRET'}
r = requests.post(AUTH_URL, data=ref_payload, headers=header)
return r
#app.route("/q")
def api_callback():
session.clear()
code = request.args.get('code')
res = requests.post(AUTH_URL, data={
"grant_type":"authorization_code",
"code":code,
"redirect_uri":REDIRECT_URI,
"client_id":CLIENT_ID,
"client_secret":CLIENT_SECRET
})
res_body = res.json()
session["token"] = res_body.get("access_token")#token
session["expires_in"] = res_body.get("expires_in")#time
session["refresh_token"] = res_body.get("refresh_token")#reflesh token
return redirect("index")
https://accounts.spotify.com/api/token is accepted as AUTH_URL
Most likely the problem is very commonplace, but I can't think of a solution now. Thanks in advance
I solved this problem. In my configurashion file i was create a veriable in which i encode my client_id and client_secret to base64 format:
ID_SEC = CLIENT_ID +':'+ CLIENT_SECRET
base64_encode = base64.b64encode(ID_SEC.encode()).decode()
After in the header i edit authorisation :
header={
'Content-Type':'application/x-www-form-urlencoded',
'Accept': 'application/json',
'Authorization': 'Basic {}'.format(base64_encode)
}
And send post requests:
r = requests.post(AUTH_URL, data=ref_payload, headers=header)

How to use annotations to create OpenAPI (Swagger) documentation on Grails 4

We are creating API documentation for an existing Grails 4 App. We are having difficulties in understanding how to use Swagger annotations.
Let's assume the following Controller:
class IntegratorController {
def maintenanceService
def saveMaintenance() {
def message = 'success'
def status = '200'
try {
def maintenanceJson = request.JSON.maintenances
def ret=maintenanceService.processMaintenanceJSON(maintenanceJson)
} catch (Exception e) {
log.error("Error to process restricions", e)
message = 'error : ${e.getMessage()}'
status = '500'
}
def result = ['message':message]
render(status: status, contentType: "application/json", text: result as JSON)
}
}
This controller expects you to send a request JSON like this example:
{ "job":42,
"maintenances": [
{"idPort":42, "idMaintenance":42, "shipName":"myship01", "obs":"asap"},
{"idPort":43, "idMaintenance":43, "shipName":"myship02", "obs":"asap"}]}
A basic annotation will be this:
#Controller("/")
class IntegratorController {
def maintenanceService
#Post(uri="/saveMaintenance", produces = MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
#Operation(summary = "Create one or more ship maintenance")
#ApiResponse(responseCode = "500", description = "If internal service throws an Exception")
def saveMaintenance() {
def message = 'success'
def status = '200'
try {
def maintenanceJson = request.JSON.maintenances
def savedMaintenances=maintenanceService.processMaintenanceJSON(maintenanceJson)
} catch (Exception e) {
log.error("Error to process restricions", e)
message = 'error : ${e.getMessage()}'
status = '500'
}
def result = ['message':message]
render(status: status, contentType: "application/json", text: result as JSON)
}
}
Where and how to annotate the request JSON sent in the post operation?
Thank you!
The request object is "scoped" by Grails. So you need to use #RequestBody annotation to declare what it is outside the method declaration. You also need to create classes to describe what it is because the JSON deserialization is loosely typed.
This is an example:
#Post(uri="/saveMaintenance", produces = MediaType.APPLICATION_JSON)
#Operation(summary = "Summary here",
description = "Description here",
requestBody = #RequestBody(description = "Inside Operation"), tags = ["IntegratorWebController"])
#RequestBody(description = "Description here", required = true,
content = #Content(schema = #Schema(implementation = YourRequestDAO.class, anyOf = [YourRequestDAO.class, YourRequestDAODependency.class])))
#ApiResponses(value=[
#ApiResponse(responseCode="200", description = "Return status=OK in success", content = #Content(mediaType = "application/json", schema = #Schema(implementation = YourResponseDAO.class))),
#ApiResponse(responseCode="404", description = "Return status=BAD_REQUEST if you mess up", content = #Content(mediaType = "application/json", schema = #Schema(implementation = YourResponseDAO.class)))])
def saveOrUpdateActivity(){
(...)
Well Swagger and OpenAPI are 'schemas' that are preloaded at runtime to build the call structure; GraphQL also has a schema as well to load its call structure.
I did a video on it here to help you understand how this works: https://youtu.be/AJJVnwULbbc
The way Grails did this prior to 4.0 was with plugins like the 'swagger plugin' or with BeAPI plugin (which I maintain).
I don't see a supported plugin in 4.0 so I don't see how they are doing this now.

Groovy httpbuilder post list params

I'm trying to consume a web service from my grails project. I'm using httpbuilder 0.7.2. Below is my http client.
static def webServiceRequest(String baseUrl, String path, def data,method=Method.GET,contentType=ContentType.JSON){
def ret = null
def http = new HTTPBuilder(baseUrl)
http.request(method, contentType) {
uri.path = path
requestContentType = ContentType.URLENC
if(method==Method.GET)
uri.query = data
else
body = data
headers.'User-Agent' = 'Mozilla/5.0 Ubuntu/8.10 Firefox/3.0.4'
response.success = { resp, json ->
println "response status: ${resp.statusLine}"
ret = json
println '--------------------'
}
}
return ret
}
The issue is coming when i'm trying to send something like this:
def input = [:]
input['indexArray'] = [1,5]
api call
def response = webServiceRequest(url,uri,input,Method.POST)
when i'm printing the value of post data in my server it shows only last value of list.
{"indexArray":"5"}
it should show both 1 and 5
If you want to send json data using contenttype application/x-www-form-urlencoded you have to explicitly convert the data before adding it to the body, you can use (data as JSON).
I am using RESTClient (nice convenience wrapper on HTTPBuilder, https://github.com/jgritman/httpbuilder/wiki/RESTClient). It is as simple as this with Spock.
RESTClient restClient = new RESTClient("http://localhost:8080")
restClient.contentType = ContentType.JSON
Also it automatically parses the JSON data, so my Spock test is:
when: "we check the server health"
HttpResponseDecorator response = restClient.get([path : "/health"]) as HttpResponseDecorator
then: "it should be up"
response != null
200 == response.status
'application/json' == response.contentType

Set headers in a groovy post request

I need to set a header in a post request: ["Authorization": request.token]
I have tried with wslite and with groovyx.net.http.HTTPBuilder but I always get a 401-Not authorized which means that I do cannot set the header right.
I have also thought of logging my request to debug it but I am not able to do that either.
With wslite this is what I do
Map<String, String> headers = new HashMap<String, String>(["Authorization": request.token])
TreeMap responseMap
def body = [amount: request.amount]
log.info(body)
try {
Response response = getRestClient().post(path: url, headers: headers) {
json body
}
responseMap = parseResponse(response)
} catch (RESTClientException e) {
log.error("Exception !: ${e.message}")
}
Regarding the groovyx.net.http.HTTPBuilder, I am reading this example https://github.com/jgritman/httpbuilder/wiki/POST-Examples but I do not see any header setting...
Can you please give me some advice on that?
I'm surprised that specifying the headers map in the post() method itself isn't working. However, here is how I've done this kind of thing in the past.
def username = ...
def password = ...
def questionId = ...
def responseText = ...
def client = new RestClient('https://myhost:1234/api/')
client.headers['Authorization'] = "Basic ${"$username:$password".bytes.encodeBase64()}"
def response = client.post(
path: "/question/$questionId/response/",
body: [text: responseText],
contentType: MediaType.APPLICATION_JSON_VALUE
)
...
Hope this helps.
Here is the method that uses Apache HTTPBuilder and that worked for me:
String encodedTokenString = "Basic " + base64EncodedCredentials
// build HTTP POST
def post = new HttpPost(bcTokenUrlString)
post.addHeader("Content-Type", "application/x-www-form-urlencoded")
post.addHeader("Authorization", encodedTokenString)
// execute
def client = HttpClientBuilder.create().build()
def response = client.execute(post)
def bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))
def authResponse = new JsonSlurper().parseText(bufferedReader.getText())

Post request by ruby code and JAva code for Rails application

i am trying to call my Rails app using Ruby code .
I m having 2 tables .
Blogposts (id,name,slug,desc)
Comments (id,data,node_id,node_type)
I m trying to post a comment through my ruby code.
The Url for me is like
http://localhost:3000/api/blogs/comment.xml?slug=blogtitle-0&comment=aaaaaaaaaaaaaaa
I dont know how to write Ruby post code for this.
The one is tried is
require 'net/http'
require 'uri'
url = URI.parse('http://localhost:3000/api/blogs/comment.xml?slug=blogtitle-0')
req = Net::HTTP::Post.new(url.path)
req.basic_auth 'aruna', 'aruna'
req.set_form_data({'comment[data]'=>'aaaaaaaaaaaaaaa'}, ';')
res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
case res
when Net::HTTPSuccess, Net::HTTPRedirection
puts res.body
else
res.error!
end
end
Please help in fixing this
Edit: The same thing i am trying using Java using Jersey library file .
Here also i am not getting the result.
The one i tried in Java is,
blogBean = objBlogWrapper.postComment(slug,comment);
public BlogBean postComment(String slug, String comment) {
System.out.println(slug+""+comment);
// Create a multivalued map to store the parameters to be send in the REST call
MultivaluedMap<String, String> newBlogParam = new MultivaluedMapImpl();
// newBlogParam.add("blogpost[slug]", slug);
// newBlogParam.add("comment[data]", comment);
newBlogParam.add("slug", slug);
newBlogParam.add("comment", comment);
BlogBean blogBean = null;
try {
blogBean = webResource.path(ConfigurationUtil.POST_COMMENT).header(ConfigurationUtil.AUTHENTICATION_HEADER, authentication)
.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).accept(MediaType.APPLICATION_XML_TYPE).post(BlogBean.class, newBlogParam);
}catch (UniformInterfaceException uie) {
if (uie.getResponse().getStatus() == 401) {
System.out.println("Can not authenticate user "+ConfigurationUtil.userName +
". Please check your username/password and try again." );
} else {
System.out.println("Error when trying to talk to app. " +
"HTTP status code "+uie.getResponse().getStatus()+"returned. Finishing.");
}
return null;
} catch (ClientHandlerException che) {
System.out.println("Error when trying to talk toapp. Network issues? " +
"Please check the following message and try again later: "+che.getMessage());
return null;
}
return blogBean;
}
where my ConfigurationUtil.POST_COMMENT="api/blogs/comment.xml";
The above doesnt show me any error nor the comment is posted ..
Please give suggestions.
Here you go,
host, phost = ['http://localhost:3000', 'http://proxyhost:2521' ]
user, password = [ 'user_name' , 'password' ]
url, p_url = [URI.parse(host), URI.parse(phost)]
resp = nil
http = Net::HTTP.new(url.host, url.port, p_url.host, p_url.port)
req = Net::HTTP::Post.new(url.path)
req.basic_auth user, password
req.set_content_type 'application/xml'
req.body = 'your_request_body'
resp = http.start{|h| h.request(req)}
You may not need a proxy host at all. But just in case if you want your request proxied through, you can use that. The resp object will have your response.
With Faraday you just do
body_resp = Faraday.post 'http://localhost:3000/api/blogs/comment.xml', {:slug => 'blogtitle-0', :comment => 'aaaaaaaaaaaaaaa'}.body
Using some external gem can help because Net::Http class in Ruby is not the most simplest API.

Resources