XmlHttpRequest and AEM Servlet - xmlhttprequest

I am making an raw ajax call on the clientside, which look like the following,
var url = '/bin/denisa/dummyServlet';
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
xhr.setRequestHeader('Accept', 'application/json, text/javascript, */*; q=0.01');
xhr.onload = function() {
if (xhr.status === 200) {
alert('deni');
}
else {
alert('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send();
to the following servlet in AEM:
#Component(
service = {
Servlet.class
},
property = {
"sling.servlet.paths=/bin/denisa/dummyServlet",
"sling.servlet.extensions=json",
"sling.servlet.methods=GET"
}
)
public class DummyServlet extends SlingSafeMethodsServlet {
private static final Logger LOG = LoggerFactory.getLogger(DummyServlet .class);
#Reference
private dummyService dummyService;
#Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(dummyService);
response.setContentType("application/json");
response.getWriter().write(gson.toJson(jsonElement));
}
}
And I got a 404, and i don't know exactly why because the path is the same, and also contentTypes. Does anybody has a clue?

Your code looks good it seems something is missing on the config side
can you log in to the felix console
http://localhost:4502/system/console/bundles
Expand you project bundle and check for your servlet
with Service ID xx Types: javax.servlet.Servlet and other details
*Also ensure the bundle is not installed and in active state
Then go to http://localhost:4502/system/console/configMgr and verify Apache Sling Servlet/Script Resolver execution paths contain /bin/ entry
If above mentioned configs are navigate to http://localhost:4502/system/console/servletresolver
check for servlet response.
These are some of the configuration which helped me to resolve 404

Related

Net Core 3.1 OData returns error 500 when using both $filter and $select and output is xml

I'm currently developing an OData API in .Net Core 3.1 which fetches data from SQL server. Using postman, I'm sending GET requests to the API with Accept headers text/xml and application/json.
With this url: <http://localhost:8008/odata/Contact?$filter=No_ eq 'T20-1234567'&$select=No_> and an application/json Accept-Header (or No Accept-Header) the response is
json response
But with Accept-Header application/xml or text/xml:
An unhandled exception was thrown by the application.
System.ArgumentException: Object of type 'System.Linq.EnumerableQuery1[Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSome1[Models.Contact]]' cannot be converted to type 'System.Collections.Generic.IEnumerable`1[Models.Contact]'.
The strange thing is that when the $select part is removed from the url, the request is correctly handled by the application (200).
My controller action:
[HttpGet]
[ODataRoute(nameof(Contact))]
public IQueryable<Contact> GetContact()
{
return _context.Contact;
}
Has anyone seen this type of behaviour?
To answer my own question, here's a possible workaround:
services
.AddMvc(config =>
{
...
config.OutputFormatters.Add(new CustomXmlOutputFormatter());
config.RespectBrowserAcceptHeader = true;
});
public class CustomXmlOutputFormatter : TextOutputFormatter
{
public CustomXmlOutputFormatter()
{
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/xml"));
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/xml"));
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
}
protected override bool CanWriteType(Type type)
{
return true;
}
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
if (context == null) throw new ArgumentNullException(nameof(context));
if (selectedEncoding == null) throw new ArgumentNullException(nameof(selectedEncoding));
var httpContext = context.HttpContext;
var json = JsonConvert.SerializeObject(new { item = context.Object });
var xml = JsonConvert.DeserializeXNode(json, "root");
var buffer = new StringBuilder(xml.ToString());
await httpContext.Response.WriteAsync(buffer.ToString());
}
}

Image HttpMessageResponse responding but not displaying?

I'm currently updating an old site to use the Hot Towel framework and one of the the things the current site does is load an image using the HTTPMessageResponse. This works fine in the the old set up however on the new set up the image is not displayed and going to the URL produces...
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.ByteArrayContent, Headers: { Content-Type: image/png }
I've had a look at the response both apps produce, and the responses from the following function match (the response is the same as above and the contents are a perfect match)...
namespace OPC.Controllers
{
public class ImageController : Controller
{
public HttpResponseMessage GetImage(int imageId)
{
var blob = new byte[10];
var context = new OPCEntity();
var ImageString = context.sp_GetImageData(imageId);
foreach (var Result in ImageString)
{
blob = Result.Data;
}
Image image;
var ms = new MemoryStream();
ms.Write(blob, 0, blob.Length);
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(ms.ToArray());
result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/png");
return result;
}
}
}
The image is set in the JS using...
image.setAttribute('src', document.location.href.match(/(^[^#]*)/)[0] + '/Image/GetImage?imageId=' + imageDetails.imageId);
Does anyone have any ideas on what I could be missing, or if anything in the Hot Towel framework could be interfering.
Many Thanks in advance.
Well I have missed something important... the fact that it should be...
public class ImageController : ApiController{}
However I have also found that the breeze web API config does conflict with the normal web API config so for the time being I've had to change BreezeWebApiConfig.cs to the following
public static class BreezeWebApiConfig {
public static void RegisterBreezePreStart() {
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "BreezeApi",
routeTemplate: "api/{controller}/{action}"
);
}
}

File upload for Netty 4.x example

How make upload http file server with Netty 4.x ? For 3.x is an example, for 4.x example only for serving static file.
I use netty-all:4.1.32.Final do upload file server
// Post request
private void formParams(HttpServerRequest request, ByteBuf content, Map<String, String> formParams, Map<String, MemoryFileUpload> fileParams) {
if (content != null) {
// POST Params
FullHttpRequest dhr = new DefaultFullHttpRequest(request.version(), request.method(), request.uri(), content, request.requestHeaders(), EmptyHttpHeaders.INSTANCE);
HttpPostRequestDecoder postDecoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), dhr);
List<InterfaceHttpData> postData = postDecoder.getBodyHttpDatas();
for (InterfaceHttpData data : postData) {
// General Post Content
if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
MemoryAttribute attribute = (MemoryAttribute) data;
formParams.put(attribute.getName(), attribute.getValue());
}
// Upload
else if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.FileUpload) {
MemoryFileUpload fileUpload = (MemoryFileUpload) data;
fileParams.put(fileUpload.getName(), fileUpload);
}
}
}
}
HttpPostRequestDecoder is not ported to 4.0.0.x yet. So there is no support for it atm. It's on the to-do-list.

How to construct message header for a HEAD response with restlet

I'm trying to create a HEAD response with restlet. Unfortunatly there is ony a #Get annotation, but the restlet author states, that you have to use a #Get, and then compare the Method.
As the documentation/specification says, there can be no body, but only a message header.
Now how to create a message header that will be send to the server, because the following code does not work, it sends this headers: HTTP/1.1 204 No Content, Content-Length: 0
protected void addResponseHeader(String name, String value) {
Form responseHeaders = (Form)getResponse().getAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS);
if (responseHeaders == null) {
responseHeaders = new Form();
getResponse().getAttributes().put(HeaderConstants.ATTRIBUTE_HEADERS, responseHeaders);
}
responseHeaders.add(new Parameter(name, value));
}
The concrete code on server-side:
#Get
public void execute() {
if (Method.HEAD.equals(getMethod())) {
//optional: getResponse().getEntity().setMediaType(MediaType.TEXT_PLAIN);
getResponse().setStatus(Status.SUCCESS_OK, "hello head");
addResponseHeader("X-my-header", "value");
}
}
The client code:
#Test
public void head() {
Request request = new Request(Method.HEAD, url);
Response response = query(request);
assertEquals(Status.SUCCESS_OK, response.getStatus());
Form form = (Form)response.getAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS);
assertEquals("value", form.getFirstValue("X-my-value")); // does fail because it is null
}
You just need to implement #Get for real : should work with a HTTP GET fine first. Then if you issue a HTTP HEAD, it will be handled automatically by the framework, nothing else to do on your side. Just focus on getting GET implemented correctly.

JavaFX: File upload to REST service / servlet fails because of missing boundary

I'm trying to upload a file using JavaFX using the HttpRequest. For this purpose I have written the following function.
function uploadFile(inputFile : File) : Void {
// check file
if (inputFile == null or not(inputFile.exists()) or inputFile.isDirectory()) {
return;
}
def httpRequest : HttpRequest = HttpRequest {
location: urlConverter.encodeURL("{serverUrl}");
source: new FileInputStream(inputFile)
method: HttpRequest.POST
headers: [
HttpHeader {
name: HttpHeader.CONTENT_TYPE
value: "multipart/form-data"
}
]
}
httpRequest.start();
}
On the server side, I am trying to handle the incoming data using the Apache Commons FileUpload API using a Jersey REST service. The code used to do this is a simple copy of the FileUpload tutorial on the Apache homepage.
#Path("Upload")
public class UploadService {
public static final String RC_OK = "OK";
public static final String RC_ERROR = "ERROR";
#POST
#Produces("text/plain")
public String handleFileUpload(#Context HttpServletRequest request) {
if (!ServletFileUpload.isMultipartContent(request)) {
return RC_ERROR;
}
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = null;
try {
items = upload.parseRequest(request);
}
catch (FileUploadException e) {
e.printStackTrace();
return RC_ERROR;
}
...
}
}
However, I get a exception at items = upload.parseRequest(request);:
org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
I guess I have to add a manual boundary info to the InputStream. Is there any easy solution to do this? Or are there even other solutions?
Have you tried just using the InputStream from HttpServletRequest like so
InputStream is = httpRequest.getInputStream();
BufferedInputStream in = new BufferedInputStream(is);
//Write out bytes
out.close();
is.close();