Sending a bunch of binary back to the user like an image:
interface API
{
#path("/data/image")
#contentType("image/png")
ubyte[] getImagePreview(string foo);
}
The function is returning a Json array with the values of the ubyte[]
Here are the list of attributes I can use:
adjustMethodStyle
bodyParam
contentType
extractHTTPMethodAndName
headerParam
method
noRoute
path
queryParam
rootPathFromName
Source: Vibe.d site
The only attribute that can do the job is contentType and it's said there that it only works with ubyte[] functions, and that's what I used.
What am I missing?
You can try hunt framework so easy use:
#Action
Response image(string imageName)
{
return new FileResponse("/data/image/" ~ imageName);
}
More read wiki:
https://github.com/huntlabs/hunt-framework/wiki/FileResponse
Related
This is regarding Sendgrid incoming mail webhook, I have referred this URL SendGrid incoming mail webhook - how do I secure my endpoint, and got some idea how to go about this, but, as I am new to MVC / WebAPI, could anyone give me the controller method code snippet to catch the JSON format HTTP post and save to my application folder.
This is the solution I found after googling and with slight modifications:
[HttpPost, HttpGet]
[EnableCors(origins: "*", headers: "*", methods: "*")]
public async Task Post()
{
if (Request.Content.IsMimeMultipartContent("form-data"))
try
{
//To get complete post in a string use the below line, not used here
string strCompletePost = await Request.Content.ReadAsStringAsync();
HttpContext context = HttpContext.Current;
string strFrom = context.Request.Form.GetValues("from")[0];
string strEmailText = context.Request.Form.GetValues("email")[0];
string strSubject = context.Request.Form.GetValues("subject")[0];
//Not useful I guess, because it always return sendgrid IP
string strSenderIP = context.Request.Form.GetValues("sender_ip")[0];
}
catch (Exception ex)
{
}
}
I tried, retrieving the values as
String to = context.Request.Params["to"];
but, the value returned is not consistent, i.e. most of the times it is returning null and occasionally returns actual value stored in it.
If anyone have a better solution, please let me know.
Thank you
If for some reason ["to"] doesn't work for you, try to get ["envelope"] value,
context.Request.Form.GetValues("envelope")[0]
which looks like
{"to":["emailto#example.com"],"from":"emailfrom#example.com"}
I am doing a PUT request to RESTfull service which changes password of a user. For the time being I have just hardcoded values of new and old password in my AJAX test my service. However it is giving me a 400 error.
AJAX call
$.ajax({
type: "PUT",
url: "api/teachers/"+user,
data: {"old":"123","new":"qwe"},
contentType: "application/json",
success: function(data,status)
{
datax = data;
alert(data+status);
ko.applyBindings(new AddMarkSheetKo(data));
},
error: function(XMLHttpRequest, textStatus, errorThrown)
{
alert(XMLHttpRequest+textStatus+ errorThrown);
// error handler here
}
});
Restful function:
#PUT
#Path("/{name}")
#Consumes(MediaType.APPLICATION_JSON)
public Response changePwd(#PathParam ("name")String name,#QueryParam ("old") String old, #QueryParam("new") String nw){
System.out.println("entered function"+old+nw);
Teacher t = DataAccessUtil.getByName(Teacher.class, name);
if(t.getPassword().equals(old)){
t.setPassword(nw);
DataAccessUtil.update(t);
return Response.ok().build();
}
else{
return Response.status(Status.BAD_REQUEST).entity("Wrong password !!!").build();
}
//return reposnse;
}
This information might be useful that on the console it prints
entered functionnullnull
So it the restfull function is called however it is not receiving the query parameters.
Any help would be really appreciated!
First, you could replace the #QueryParam annotations with #FormParam ones to retrieve the 'new' and 'old' parameters of the PUT request. Then, you should remove the #Consumes("application/json") annotation and contentType:application/json from your server and browser side code, and finally replace the submitted data in JSON format into something like 'new=qwe&old=123'.
If you want to stay with a content in JSON format, you should probably map the incoming body with an entity (ie, a Java class annotated with JAXB annotations), so that the JAX-RS implementation you use could unmarshall the incoming JSON content into a Java object.
HTH.
I am writing a file service using Asp.Net’s Web Api. The service retrieves files (Css, Excel, Csv, etc.) from SQL Server and serves them up in response to Get requests.
My first test case is for Css files. The issue is that, while I can see the correct data on the server side, when the browser retrieves/decodes it, the results are mangled. The issue appears to be related to the encodings.
Here are the request/response headers in FireFox:
When I click on the response tab in FireBug, here’s what it looks like:
The results look like ascii being displayed as utf8. This is the html view in FireBug:
The above example is an iFrame inside a Facebook application which is running ssl.
If I take the url and open it directly in the browser, it works and correctly displays my Css:
In summary, when I retrieve my Css file from a tag inside my Facebook app, I get garbage (encoding issue?). If I retrieve it straight from the browser, it works.
My CssFormatter MediaTypeFormatter code:
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
var taskSource = new TaskCompletionSource<object>();
try
{
var incomingFile = value as FileRestService.Entity.IFile;
var ms = new MemoryStream(incomingFile.DataBuffer);
ms.CopyTo(writeStream);
ms.Flush();
taskSource.SetResult(writeStream);
}
catch (Exception e)
{
taskSource.SetException(e);
}
return taskSource.Task;
}
Am I creating the response stream incorrectly? I noticed that the response headers do not specify the encoding. Is this an issue?
I find the easiest way to handle this is to write something along the lines of (here's the important details):
public class Formatter : MediaTypeFormatter {
// TODO override the constructor to add some mappings or some other way for this formatter to be picked up
// TODO override CanReadType and CanWriteType according to your rules
public override void SetDefaultContentHeaders(Type t, HttpContentHeaders headers, string mediaType) {
base.SetDefaultContentHeaders(t, headers, mediaType);
headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {
FileName = "SomeName.ext"
};
}
public override Task WriteToStreamAsync(Type t, object value, Stream s, HttpContentHeaders headers, TransportContext context) {
return Task.Factory.StartNew(() => {
// TODO code to write to the output stream, flush it but don't explicitly close it
});
}
}
I'm using backbone.js to interact with a REST API that, when posting to it to create a new resource, responds with a status of 201, a 'Location' header pointing to the resource's URI, but an empty body.
When I create a new model at the moment, its successful, but the local representation of the model only contains the properties I explicitly set, not any of the properties that would be set on the server (created_date, etc.)
From what I understand, Backbone would update its representation of the model with data in the body, if there were any. But, since there isn't, it doesn't.
So, clearly, I need to use the location in the Location header to update the model, but what's the best way to do this.
My current mindset is that I would have to parse the url from the header, split out the id, set the id for the model, then tell the model to fetch().
This seems really messy. Is there a cleaner way to do it?
I have some influence over the API. Is the best solution to try to get the API author to return the new model as the body of the response (keeping the 201 and the location header as well)?
Thanks!
Sounds like you will have to do a little customization.
Perhaps override the parse method and url method of your model class inherited from
Backbone.Model.
The inherited functions are:
url : function() {
var base = getUrl(this.collection);
if (this.isNew()) return base;
return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + this.id;
},
parse : function(resp) {
return resp;
},
and you could try something like:
parse: function(resp, xhr) {
this._url = xhr.getResponseHeader('location')
return resp
}
url: function() {
return this._url
}
Yes, backbone.js really wants the result of a save (be it PUT or POST) to be a parseable body which can be used to update the model. If, as you say, you have influence over the API, you should see if you can arrange for the content body to contain the resource attributes.
As you point out, its makes little sense to make a second over-the-wire call to fully materialize the model.
It may be that a status code of 200 is more appropriate. Purists may believe that a 201 status code implies only a location is returned and not the entity. Clearly, that doesn't make sense in this case.
With Backbone 0.9.9, I couldn't get the accepted answer to work. The signature of the parse function seems to have changed in an older version, and the xhr object is no longer available in the function signature.
This is an example of what I did, to make it work with Backbone v0.9.9 and jQuery 1.8.3 (using a Deferred Object/Promise), relying on the jqXHR object returned by Backbone.Model.save() :
window.CompanyView = Backbone.View.extend({
// ... omitted other functions...
// Invoked on a form submit
createCompany: function(event) {
event.preventDefault();
// Store a reference to the model for use in the promise
var model = this.model;
// Backbone.Model.save returns a jqXHR object
var xhr = model.save();
xhr.done(function(resp, status, xhr) {
if (!model.get("id") && status == "success" && xhr.status == 201) {
var location = xhr.getResponseHeader("location");
if (location) {
// The REST API sends back a Location header of format http://foo/rest/companys/id
// Split and obtain the last fragment
var fragments = location.split("/");
var id = fragments[fragments.length - 1];
// Set the id attribute of the Backbone model. This also updates the id property
model.set("id", id);
app.navigate('companys/' + model.id, {trigger: true});
}
}
});
}
});
I did not use the success callback that could be specified in the options hash provided to the Backbone.Model.save function, since that callback is invoked before the XHR response is received. That is, it is pointless to store a reference to the jqXHR object and use it in the success callback, since the jqXHR would not contain any response headers (yet) when the callback is invoked.
Another other to solve this would be to write a custom Backbone.sync implementation, but I didn't prefer this approach.
I am building a REST API for my project. The API for getting a given user's INFO is:
api.com/users/[USER-ID]
I would like to also allow the client to pass in a list of user IDs. How can I construct the API so that it is RESTful and takes in a list of user ID's?
If you are passing all your parameters on the URL, then probably comma separated values would be the best choice. Then you would have an URL template like the following:
api.com/users?id=id1,id2,id3,id4,id5
api.com/users?id=id1,id2,id3,id4,id5
api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5
IMO, above calls does not looks RESTful, however these are quick and efficient workaround (y). But length of the URL is limited by webserver, eg tomcat.
RESTful attempt:
POST http://example.com/api/batchtask
[
{
method : "GET",
headers : [..],
url : "/users/id1"
},
{
method : "GET",
headers : [..],
url : "/users/id2"
}
]
Server will reply URI of newly created batchtask resource.
201 Created
Location: "http://example.com/api/batchtask/1254"
Now client can fetch batch response or task progress by polling
GET http://example.com/api/batchtask/1254
This is how others attempted to solve this issue:
Google Drive
Facebook
Microsoft
Subbu Allamaraju
I find another way of doing the same thing by using #PathParam. Here is the code sample.
#GET
#Path("data/xml/{Ids}")
#Produces("application/xml")
public Object getData(#PathParam("zrssIds") String Ids)
{
System.out.println("zrssIds = " + Ids);
//Here you need to use String tokenizer to make the array from the string.
}
Call the service by using following url.
http://localhost:8080/MyServices/resources/cm/data/xml/12,13,56,76
where
http://localhost:8080/[War File Name]/[Servlet Mapping]/[Class Path]/data/xml/12,13,56,76
As much as I prefer this approach:-
api.com/users?id=id1,id2,id3,id4,id5
The correct way is
api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5
or
api.com/users?ids=id1&ids=id2&ids=id3&ids=id4&ids=id5
This is how rack does it. This is how php does it. This is how node does it as well...
There seems to be a few ways to achieve this. I'd like to offer how I solve it:
GET /users/<id>[,id,...]
It does have limitation on the amount of ids that can be specified because of URI-length limits - which I find a good thing as to avoid abuse of the endpoint.
I prefer to use path parameters for IDs and keep querystring params dedicated to filters. It maintains RESTful-ness by ensuring the document responding at the URI can still be considered a resource and could still be cached (although there are some hoops to jump to cache it effectively).
I'm interested in comments in my hunt for the ideal solution to this form :)
You can build a Rest API or a restful project using ASP.NET MVC and return data as a JSON.
An example controller function would be:
public JsonpResult GetUsers(string userIds)
{
var values = JsonConvert.DeserializeObject<List<int>>(userIds);
var users = _userRepository.GetAllUsersByIds(userIds);
var collection = users.Select(user => new { id = user.Id, fullname = user.FirstName +" "+ user.LastName });
var result = new { users = collection };
return this.Jsonp(result);
}
public IQueryable<User> GetAllUsersByIds(List<int> ids)
{
return _db.Users.Where(c=> ids.Contains(c.Id));
}
Then you just call the GetUsers function via a regular AJAX function supplying the array of Ids(in this case I am using jQuery stringify to send the array as string and dematerialize it back in the controller but you can just send the array of ints and receive it as an array of int's in the controller). I've build an entire Restful API using ASP.NET MVC that returns the data as cross domain json and that can be used from any app. That of course if you can use ASP.NET MVC.
function GetUsers()
{
var link = '<%= ResolveUrl("~")%>users?callback=?';
var userIds = [];
$('#multiselect :selected').each(function (i, selected) {
userIds[i] = $(selected).val();
});
$.ajax({
url: link,
traditional: true,
data: { 'userIds': JSON.stringify(userIds) },
dataType: "jsonp",
jsonpCallback: "refreshUsers"
});
}