Writing a Custom Gateway Error Response using a mapping template in VTL for AWS - mapping

I'm writing a mapping template for an AWS API Gateway integration response to return a custom error output format.
My function looks like this:
{
"gw_code":"$gw_code",
"er_code":"$er_code",
"code":"$gw_code" + "-" + "$er_code",
"developerMessage":"$developerMessage"
"message":"$message"
"gw_msg":"$code
$developerMessage"
}
#set ($er_num = "200")
#set ($er_msg = "ACCESS_DENIED")
#if($code == "403-001" && $developerMessage == "Unauthorized")
// Ignore
#else
{
"code" : "403-001",
"developerMessage" : "Unauthorized."
}
#end
But the URL prints an internal server error as the output:
{"message": "Internal server error"}
I re-read the VTL documentation guide and attempted to modify the code by boiling it down to this:
#set($messageOverride = "foo")
{
#if($status == "403-001" && $developerMessage = "Unauthorized")
// Ignore
#else
#if($inputRoot.toString().contains("error"))
"code" : "403-001",
"developerMessage" : "Unauthorized."
#end
#end
#end
}
But the internal server error is still showing up and I can't figure out what I'm doing wrong.

Your second code is a big improvement from the first, however it still needs some work.
Your function should look something like this:
#set($inputRoot = $input.path('$'))
#if($status == "403-001" && $developerMessage = <TBD>)
// Ignore
#else
#if($inputRoot.toString().contains("error"))
#set($context.responseOverride.status = 403)
#set($context.requestOverride.header.devMessage = $message1Override)
#end
#end
#end
I haven't tested it, but in theory, it should work.

Related

Create common component with Swagger annotations

I am using swagger-annotation for my spring-boot project.
I would like to return a common response code contract for each resource of my controller.
In the doc : https://github.com/swagger-api/swagger-core/wiki/annotations#apiresponses-apiresponse
they talk about #ApiResponses but I cannot put the annotation at the class level.
Here is what I did:
#Api(value = "Title",
description = "What this controller is about"
)
#ApiResponses(value = {
#ApiResponse(code = 400, message = "Bad stuff from the client"),
#ApiResponse(code = 404, message = "Item not found") }
)
public class FooBarController {
...
}
But the problem is that 400 - Bad stuff from the client and 404 - Item not found are never shown in the generated doc.
In the official doc of swagger I have seen this section: https://swagger.io/docs/specification/describing-responses/#reuse
Question: How can I create a kind of "reusable component" with java annotations ?
Thanks
According to the documentation, you can do this at the Docket level.
.useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.GET,
newArrayList(new ResponseMessageBuilder()
.code(400)
.message("Bad stuff from the client")
.build()))
https://springfox.github.io/springfox/docs/current/#springfox-spring-mvc-and-spring-boot
Update:
If you want to go the annotation route, you can create your own and place it on your controller.
#Documented
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
#ApiResponses(value = {
#ApiResponse(code = 400, message = "Bad stuff from the client"),
#ApiResponse(code = 404, message = "Item not found") }
)
public #interface GlobalApiReponses {
}
Then use it..
#Api(value = "Title",
description = "What this controller is about"
)
#GlobalApiReponses
public class FooBarController
A combination of approaches might be a good option as well.
The #Target(ElementType.TYPE) means you can apply this at the class level. You can do the same for methods by using the ElemenType.METHOD.

MMRecord: What should KeyPathforResponseObject return for the whole response?

The JSON response which I get from the API will be something like this
(
{
key11:value11,
key12:value12,
},
{
key21:value21,
key22:value22,
}
)
So, when I subclass MMRecord and do this
+ (NSString *)keyPathForResponseObject {
return ___;
}
What should I return from here, #"" or #"default" or something else?
I searched the documentation, it says
Default is whatever is returned by this method on the MMRecord subclass.
What does that mean?
I'm pretty new to iOS. Help me out! I'm using MMRecord-1.3.0
+ (NSString *)keyPathForResponseObject {
return nil; //To capture the entire response
}

Can i change the server url with sudzc?

I am trying to generate source code from a wsdl file for iOS. I've stumbled upon a couple of tools and so far wsclient++ and sudzc at least seem to work. But I need to send requests to different servers with the same soap interface, depending on the state of the iOS app.
In the source code generated by wsclient I can set the server URL via
MyWebService* ws = [MyWebService service];
// // set base url for entire application
[SoapWebService setGlobalBaseUrl: #"http://domain.com"];
NSError* error = nil;
Result* rs = [ws callMethod: p1 param2:p2 error:&error];
Which would me allow me to do something like
if(condition1) [SoapWebService setGlobalBaseUrl: #"http://betaserver.com"];
if(condition2) [SoapWebService setGlobalBaseUrl: #"http://developserver.com"];
if(condition3) [SoapWebService setGlobalBaseUrl: #"http://liveserver.com"];
Is there a way to archive something similar with the source code generated by sudzc?
As long as the soap is the same response you shouldn't have a problem using your code. There is a file that stores the server address. The code generated by sudzc can be modified to any address. I actually created a dynamic way of hitting servers. I will find the file and code I used to do this.
You can search the project for your domain you used for sudzc.
I'm not in front of a mac right now, but I will update later.
UPDATE:
Ok, so I created a settings tab and allowed the user to input a specific ip address if necessary. It saves the IP address in a dictionary and then this file retrieves it from the dictionary. I left some of my original comments and added some in the code so you can see both ways. If it confuses you let me know and I'll edit again. In my sudzc generated code I modified the file to this:
/*
wsUpdateQOH.m
The implementation classes and methods for the wsUpdateQOH web service.
Generated by SudzC.com
*/
#import "wsUpdateQOH.h"
#import "Soap.h"
#import "Settings.h"
#define URL #"http://%#/webServiceAddress/updateqoh.asmx"
/* Implementation of the service */
#implementation wsUpdateQOH
- (id) init
{
if(self = [super init])
{
// take out hard coded address and add variable to have a dynamic IP #"http://www.site.com/webServiceAddress/updateqoh.asmx"
// here is the dictionary return and format of the url string
NSString *savedValue = [[NSUserDefaults standardUserDefaults] stringForKey:#"serverIP"];
self.serviceUrl = [[NSString alloc] initWithFormat:URL, savedValue];
// uncomment for a hard coded address self.serviceUrl = #"http://%#/webServiceAddress/updateqoh.asmx";
self.namespace = #"http://tempuri.org/webServiceAddress/UpdateQOH";
self.headers = nil;
self.logging = NO;
}
return self;
}
- (id) initWithUsername: (NSString*) username andPassword: (NSString*) password {
if(self = [super initWithUsername:username andPassword:password]) {
}
return self;
}
+ (wsUpdateQOH*) service {
return [wsUpdateQOH serviceWithUsername:nil andPassword:nil];
}
+ (wsUpdateQOH*) serviceWithUsername: (NSString*) username andPassword: (NSString*) password {
return [[[wsUpdateQOH alloc] initWithUsername:username andPassword:password] autorelease];
}
// *** Below here is the soap actions ***

Grails / Cobertura report - conditional coverage doesn't make sense

What could cause something like this:
The line def result shows only 2/6 branches covered, even though it has NO BRANCHES, while the following line, which actually has a conditional, is ok.
What's going on? I verified that the cobertura.ser is getting cleaned up between builds.
any idea where I can get the source for that JAR?
jar and souce code for disableOptimizationsTransformation
Also - any idea how to include that JAR on classpath ONLY for the test-app build phase?
// Remove the jar before the war is bundled
grails.war.resources = { stagingDir ->
delete(file:"${stagingDir}/WEB-INF/lib/DisableOptimizationsTransformation-0.1-SNAPSHOT.jar")
}
from other post here
Same discussion also appeared in the official forum, see Branch coverage issues .
#rgarcia gave an excellent little tool jar to disable the AST optimization so that Cobertura is able to compute the coverage correctly.
To use the jar, just put it in your myapp\lib folder and then test-app -coverage:)
I've noticed the same thing in our grails projects - I think this is caused by the "optimization" branches the groovy compiler creates.
For example - this code
def deleteSomething(params) {
def result
if(params.something && params.somethingelse)
result = "something"
else result = "something else"
}
looks like this when compiled
public Object deleteSomething(Object params)
{
CallSite[] arrayOfCallSite = $getCallSiteArray(); Object result = null; if ((!BytecodeInterface8.isOrigZ()) || (__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) {
if (((DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[2].callGetProperty(params))) && (DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[3].callGetProperty(params))) ? 1 : 0) != 0) {
String str1 = "something"; result = str1; return str1; } else {
String str2 = "something else"; result = str2; return str2;
}
}
else if (((DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[4].callGetProperty(params))) && (DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[5].callGetProperty(params))) ? 1 : 0) != 0) {
String str3 = "something"; result = str3; return str3; } else {
String str4 = "something else"; result = str4; return str4; } return null;
}
More discussion here.

The youtube API sometimes throws error: Call to a member function children() on a non-object

When i launch the php script, sometime works fine, but many other times it retrieve me this errror
Fatal error: Call to a member function children() on a non-object in
/membri/americanhorizon/ytvideo/rilevametadatadaurlyoutube.php on line
21
This is the first part of the code
// set feed URL
$feedURL = 'http://gdata.youtube.com/feeds/api/videos/dZec2Lbr_r8';
// read feed into SimpleXML object
$entry = simplexml_load_file($feedURL);
$video = parseVideoEntry($entry);
function parseVideoEntry($entry) {
$obj= new stdClass;
// get nodes in media: namespace for media information
$media = $entry->children('http://search.yahoo.com/mrss/'); //<----this is the doomed line 21
UPDATE: solution adopted
for ($i=0 ; $i< count($fileArray); $i++)
{
// set feed URL
$feedURL = 'http://gdata.youtube.com/feeds/api/videos/'.$fileArray[$i];
// read feed into SimpleXML object
$entry = simplexml_load_file($feedURL);
if (is_object($entry))
{
$video = parseVideoEntry($entry);
echo ($video->description."|".$video->length);
echo "<br>";
}
else
{
$i--;
}
}
In this mode i force the script to re-check the file that caused the error
You are first of all calling a function:
$entry = simplexml_load_file($feedURL);
That function has a return value. You find it documented on the manual page of that function:
http://php.net/simplexml_load_file
Then you use that return value in form of a variable $entry without verifying that the function call was successful.
Because of that, you run into an error next. However your error/mistake is how you treat the return value of the function.
Not dealing with return values properly is like calling for trouble. Read about the function you use, check the return value(s) and proceed according to success or error conditions.
$entry = simplexml_load_file($feedURL);
if (FALSE === $entry)
{
// youtube not available.
}
else
{
// that's what I love!
}
Sometimes? Really?
Take a look at this:
<?php
$dummy; //IN FACT, this var is NULL now
// Will throw exactly the same error you get
$dummy->children();
Why? Because, we can call method from an object type.
So, if you wanna avoid errors like this one, next time you would call the method ensure that it's "possible".
<?php
if ( is_object($dummy) && method_exists($dummy, 'children') ){
//sure it works
$dummy->children();
}

Resources