How to change input soap request as per test data in loadrunner? - web-services

I am working with one soap request where we need to pass,single data in one parameter and in 2nd iteration we need to pass multiple test data in same input request.Please help me how to change input soap request as per test data,please find below soap requests for single and multiple requests.
Single Request:
<ReqDtls>
<vReqs>
<amount>1.00</amount>
<cardNo>8897654778999</cardNo>
</Reqs>
<cardType>caredit</cardType>
</ReqDtls>
Multiple Requests:In same soap input requests,it is changing dynamically from POS system but i want to perform in loadrunner.
<ReqDtls>
<vReqs>
<amount>1.00</amount>
<cardNo>8897654778999</cardNo>
</Reqs>
<vReqs>
<amount>2.00</amount>
<cardNo>890897654778999</cardNo>
</Reqs>
<cardType>caredit</cardType>
</ReqDtls>
Any code in vugen to pass this type of values from excel file for loadtesting,please help how to do this one

This is where you will use your foundation skills in programming as well as a web_custom_request() (Potentially) to send your own custom string.
Notice the repeated piece here
<vReqs>
<amount>{amount_variable}</amount>
<cardNo>{card_variable}</cardNo>
</Reqs>
You have a defined header
<ReqDtls>
And a defined footer
<cardType>caredit</cardType>
</ReqDtls>
This now becomes a matter of string concatenation in C and turning the variables into literals. Consider a loop and lowly sprintf() for this task. Note, variable declarations are not included in the code fragment
sprintf(mybigstring,"<ReqDtls>\r");
for (myloopcounter=1;myloopcounter<=mylooplimit;myloopcounter++)
{
sprintf(mybigstring,
"%s%s",
mybigstring,
lr_eval_string("<vReqs>\r<amount>{amount_variable}</amount>\r<cardNo>{card_variable}</cardNo>\r</Reqs>\r") );
lr_advance_param("amount_variable");
lr_advance_param("card_variable");
}
sprintf(mybigstring,"%s%s",mybigstring,"<cardType>caredit</cardType>\r</ReqDtls>");
The above is directly from noggin to screen so it may require a bit if fiddling, but it should give you an idea for a path.
Once you have your string, then you can use it in whatever request as needed.

Related

How to modify the HTTP::Response after it has been written to

I'm trying to write some tooling for Crystal (specifically Kemal) where I can see if the response content type is text/html and modify the response body thats has already been written to the HTTP::Response before it is sent to the client by injecting an HTML element into the existing html response body.
I've noticed that HTTP::Server::Response is write-only, but things like Gzip::Writer are able to modify the body.
How can I modify the HTTP::Server::Response html body before it is sent to the client?
It's written in Crystal, so let's just take a look at the source on how others do this.
Taking the CompressHandler as an example, the basic idea is to replace the response's IO with something that allows the desired control:
context.response.output = Gzip::Writer.new(context.response.output, sync_close: true)
# ...
call_next(context)
So how can we make use of that to modify the response that's being written?
A naive (and slow) example would be to just keep hold of the original output and provide a IO::Memory instead:
client = context.response.output
io = IO::Memory.new
context.response.output = io
call_next(context)
body = io.to_s
new_body = inject_html(body)
client.print new_body
Of course that would only work when this handler comes before any handler that turns the response into non-plaintext (like the above CompressHandler).
A smarter solution would provide a custom IO implementation that just wraps the original IO, watching what's written to it and inject whatever it wants to inject at the right point. Examples of such wrapping IOs can be found at IO::Delimited, IO::Sized and IO::MultieWriter among others, the pattern is really common to prevent unnecessary allocations.

Reading Jetty Server Request body without making it null

I have a Jetty.Server.Request object, which is an HTTP request whose body I need to use in multiple methods.
I access the body's contents like so -
String contents = baseRequest.getReader().readLine();
However, this seems to remove the body from the HTTP request. If I then try to access it again like so -
String contents2 = baseRequest.getReader().readLine();
contents2 will be null.
How can I read the body of the request object without affecting the request?
Per the Servlet spec, the stream is only available once.
Make a copy of it yourself (either to memory, or to disk for later reading)
This is by design, as many request bodies can by quite large and there simply wouldn't be enough memory to handle rereads in a sane way.
Be sure you check out the prior answers for this:
Http Servlet request lose params from POST body after read it once
As those answer demonstrate a few ways to accomplish multiple reads of the same request body.

How to call a webservice including parameters list type in Smartface

I am trying to call a webservice in smartface by using Data Source Wizard. Webservice has input parameters whose types are list of int and some other basic types (int, string etc). Data Source Wizard sees these parameters (lists) as string not as list of int. When i try to call webservice (i leave lists/strings empty) i am getting the following error.
"There has been a netwok error, please try again later"
Is there anyone who knows how to call such webservice in Smartface ?
WebServices uses xml structure because of that reason all the inputs and outputs are should be string. It is hard to say the reason of that error.
I can suggest you to read the documents at the link ( Data & Network Section )
http://www.smartface.io/developer/guides/
I used this call
SMF.storeVariable("EmailID","Pages.Page1.EditBox1.Text", false, false);
SMF.Net.EmailInsert.run();
but still my data is not going from my editbox to the webservice.

Dynamic messages with gettext (AngularJS)

I have a application with a Django backend and an AngularJS front-end.
I use the angular-gettext plugin along with Grunt to handle translations.
The thing is, I sometimes received dynamic strings from my backend through the API. For instance a MySQL error about a foreign key constraint or duplicate key entry.
How can I add this strings to the .pot file or non harcoded string in general ?
I've tried to following but of course it cannot work :
angular.module('app').factory('HttpInterceptor', ['$q', '$injector', '$rootScope', '$cookieStore', 'gettext', function ($q, $injector, $rootScope, $cookieStore, gettext) {
responseError: function (rejection) {
gettext('static string'); //it works
gettext(rejection.data.error); //does not work
$rootScope.$emit('errorModal', rejection.data);
}
// Return the promise rejection.
return $q.reject(rejection);
}
};
}]);
})();
One solution I could think of would be to write every dynamic strings into a JSON object. Send this json to server and from there, write a static file containing these strings so gettext can extract them.
What do you suggest ?
I also use angular-gettext and have strings returned from the server that need to be translated. We did not like the idea of having a separate translation system for those messages so we send them over in the default language like normal.
To allow this to work we did two things. We created a function in our backend which we can call to retrieve all the possible strings to translate. In our case it's mainly static data that only changes once in a while. Ideally this would be automated but it's fine for now.
That list is formatted properly through code into html with the translate tag. This file is not deployed, it is just there to allow the extraction task to find the strings.
Secondly we created a filter to do the translation on the interpolated value, so instead of translating {{foo}} it will translate the word bar if that's was the value of foo. We called this postTranslate and it's a simple:
angular
.module('app')
.filter('postTranslate', ['gettextCatalog', function (gettextCatalog) {
return function (s) {
return gettextCatalog.getString(s);
};
}]);
As for things that are not in the database we have another file for those where we manually put them in. So your error messages may go here.
If errors are all you are worried about though, you may rather consider not showing all the error messages directly and instead determine what user friendly error message to show. That user friendly error message is in the front end and therefore circumvents all of this other headache :)

How do I debug mangled soap requests?

Lately, we've been seeing exceptions like this in our .NET (.asmx) webservices:
System.Web.Services.Protocols.SoapException: Server was unable to read request. ---> System.InvalidOperationException: There is an error in XML document (868, -3932). ---> System.Xml.XmlException: '.', hexadecimal value 0x00, is an invalid character. Line 868, position -3932.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String[] args)
at System.Xml.XmlTextReaderImpl.Throw(Int32 pos, String res, String[] args)
at System.Xml.XmlTextReaderImpl.ThrowInvalidChar(Int32 pos, Char invChar)
at System.Xml.XmlTextReaderImpl.ParseNumericCharRefInline(Int32 startPos, Boolean expand, BufferBuilder internalSubsetBuilder, Int32& charCount, EntityType& entityType)
at System.Xml.XmlTextReaderImpl.ParseText(Int32& startPos, Int32& endPos, Int32& outOrChars)
at System.Xml.XmlTextReaderImpl.ParseText()
at System.Xml.XmlTextReaderImpl.ParseElementContent()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlTextReader.Read()
at System.Web.Services.Protocols.SoapServerProtocol.SoapEnvelopeReader.Read()
at System.Xml.XmlReader.ReadElementString()
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read14_SendErrlog()
at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer12.Deserialize(XmlSerializationReader reader)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
--- End of inner exception stack trace ---
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
How can I debug this exception? This exception is getting reported to us from a SOAP filter which looks for exceptions in message.Stage = SoapMessageStage.AfterSerialize.
Is there any way to get at the original soap request? How do I get an invalid character at line 868, column -3932? How can there a negative column 3932?
This is one of the irritating things about the Microsoft web services approach -- if the request cannot be deserialized into the objects in your web method signature then the service consumer gets a cryptic message. And to top it off, the request never makes it into your web service because it cannot be deserialzied so you can't handle the error gracefully.
What I would do to help with these types of issues is to create a new SoapExtension that simply lets you output the raw XML to a destination that is convenient for you (file or Trace to be read by DebugView or whatever else you like). The code would go in the BeforeDeserialize stage. You could enable the SoapExtension via web.config in the event you wanted to investigate one of these issues. The downside of using the web.config to add the SoapExtension is that it will be active for the entire web application. You could add some additional custom configuration that would allow your service to only log information for a specific endpoint or a specific web method if you wanted.
Usually, just by seeing the incoming XML you can see what the problem is. If not, then you could try to manually run the captured XML through small program that invokes the XML serializer and see if you can find out what is going on. Another useful tool is Web Service Studio 2 which is a test harness which lets you enter data and invoke your service (and also submit any XML you want).
In terms of your specific issue, here is my take/guess. It looks like ASCII character null is getting encoded and sent to your service which is invalid according to the XML Spec. The simple answer is not to send that character. But who is sending that character? Is it a .NET client? Do you have control over the client? If you need to work around someone else's bug, then you may have to replace the offending character(s) with another character (perhaps empty string).
You should be able to get the original message by using another SoapExtension. In fact, the same extension could probably be modified to make a copy of the input, and to discard it if there is no exception. The original input would then be available to you if an exception occurred.
You could also use an external tool like Fiddler to watch what's being sent to you.
FYI: SoapException.Message is intentionally left vague to prevent exposing too much information which could potentially be used to exploit the system.
For your particular case I'd take John's advice and install Fiddler to monitor the actual HTTP traffic and view the message on the wire.
The portion of your exception that jumps out at me is the "hexadecimal value 0x00, is an invalid character" but as you mentioned the line number it points to is bunk--so it's nothing concrete.
What kind of parameters do you pass to the service? Are you doing any kind of custom encoding with a SOAP extension? Any additional SOAP headers being added?