Ejabberd Bosh responses with no <features> element - ejabberd

I am trying to use the bosh module which is up and running on my ejabberd server.
The client (using jabbernet) starts by sending:
<body content="text/xml; charset=utf-8" to="localhost" wait="60" hold="1"
xml:lang="en-GB" rid="1368823140" xmlns="http://jabber.org/protocol/httpbind" />
Then I get from the server the response without a element:
<body authid='17254393595248629793' xmlns='http://jabber.org/protocol/httpbind' sid='54a265d3d69252744d63d2cf6ec74d366aa24f3b'
wait='60' ver='1.11' polling='2' inactivity='30' hold='1'
xmpp:restartlogic='true' requests='2' secure='true' maxpause='120'
xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='localhost'/>
Then, according to xep-0206:
If no stream:features element is included in the connection manager's session creation response, then the client SHOULD send empty request elements until it receives a response containing a element.
So the client sends every 2 seconds:
<body to="localhost" sid="54a265d3d69252744d63d2cf6ec74d366aa24f3b" rid="1368823142" xmlns="http://jabber.org/protocol/httpbind" />
But gets from ejabberd server only:
<body xmlns='http://jabber.org/protocol/httpbind'/>
And eventually (after 30 seconds) it fails with:
<body type='terminate' condition='remote-stream-error' xmlns='http://jabber.org/protocol/httpbind'/>
What am I doing wrong?

Related

Haproxy frontend configuration to replace response header depending on query string

I used the following haproxy configuration in frontend to modify the response header of requests depending on a query string:
frontend my-frontend
acl is-foo urlp(foo) 1
http-response replace-header Set-Cookie "(.*)" "\1; SameSite=None" if is-foo
Depending on my information from the docs the acl should match for all requests like
example.com?a=b&foo=1&bar=2
example.com?foo=1
example.com?a=b&foo=1
And it should not match for requests like
example.com?a=b&foo=0&bar=2
example.com?a=b
example.com?a=b&foo=bar
The actual result is that the acl matches never.
If i invert the if i.e.: if !is-foo the replace-header happens on every request.
So the problem must be the acl which matches never.
I use haproxy 2.0.15
I got it working by myself.
It seems to be the case that urlp(foo) is not present at runtime when it has been executed for http-response.
So we need to store its value in a temporary variable using set-var(custom.name), before. At runtime in if condition we can access it with var(custom.name) and match it against our condition. I used urlp_val() instead of urlp() here because the value will be casted to int immediately.
frontend my-frontend
http-request set-var(txn.foo) urlp_val(foo)
http-response replace-header Set-Cookie "(.*)" "\1; SameSite=None" if { var(txn.foo) eq 1 }
Thank you for traveling.

jMeter not applying variable to header manager

I'm using Apache JMeter 3.2 r1790748 on Mac.
I have a setUp Thread Group making an authentication call. The call works and outputs the tokens correctly. Now I need to pass that token to the HTTP Header Manager for all the calls I'm making.
First of all, here's my token json output:
{
"access_token": "aaaaaa555555555",
"token_type": "Access",
"user_id": "5555"
}
Here's what my HTTP Header manager looks like:
1 value: Authorization : Bearer ${access_token}
My network call:
GET https://my_server.com/some_path
GET data:
[no cookies]
Request Headers:
Connection: close
Authorization: Bearer ${access_token}
Host: my_server.com
User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_91)
As you can see, the variable access_token is not being replaced with the value from the setup call.
What I've tried:
BeanShell PostProcessor:
I created this script, and it actually parses and outputs the access_token properly:
import org.apache.jmeter.protocol.http.control.Header;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.JSONParser;
String jsonString = prev.getResponseDataAsString();
log.info("jsonString = " + jsonString);
JSONParser parser = new JSONParser(JSONParser.MODE_JSON_SIMPLE);
JSONObject json = (JSONObject) parser.parse(jsonString);
String access_token = json.getAsString("access_token");
log.info("access_token = " + access_token);
vars.put("access_token", access_token);
JSON Extractor:
Apply to: Main sample and sub-samples
Variable names: access_token
JSON Path expressions: access_token
Match No. (0 for Random): 1
Compute concatenation var (suffix _ALL): unchecked
Default Values: none
Any ideas as to why the header manager is not applying the value of the access_token result?
Thanks!
Since you set a variable in setUp Thread Group, you cannot use it in another thread groups, since thread groups don't share variables, only properties.
So in order to pass authentication, you need to save it as a property:
${__setProperty(access_token, ${access_token})};
In this example I am using value of variable named access_token (already set, but only available in setUp thread group) to set property with the same name, which will be available across thread groups. Or change BeanShell post-processor, add:
props.put("access_token", access_token);
And then in the other thread group, you retrieve it using __P or __property function:
${__P(access_token)}
Also keep in mind that HTTP Header Manager initializes before any thread starts, so you can't use variables there for that reason too. Check this question for instance.
If you still see empty value, I recommend adding Debug Sampler (with both JMeter Properties and JMeter Variables enabled) in both thread groups, and checking where the breakage is (on saving or retrieving).
As per Functions and Variables chapter of the JMeter User Manual
Variables are local to a thread; properties are common to all threads, and need to be referenced using the __P or __property function
So the variable you define in the setUp Thread Group cannot be accessed by:
other threads in the same Thread Group
other threads outside the Thread Group
So my recommendations are:
Switch to JMeter Properties instead of Jmeter Variables, JMeter Properties are global to all threads and in fact the whole JVM instance
Switch to JSR223 PostProcessor with Groovy language instead of Beanshell PostProcessor, JSR223 Elements performance is much better, moreover Groovy has built-in JSON support.
So:
The relevant Groovy code for getting access_token attribute value and storing it into the relevant property would be :
props.put('access_token', new groovy.json.JsonSlurper().parse(prev.getResponseData()).access_token)
You can refer the value in the HTTP Header Manager (or wherever you require) as:
${__P(access_token,)}

How can I verify the content of a POST Body with MockWebServer?

I have several unit tests that use Squares OkHttps MockWebServer. The tests run all fine, and everything works very well. The one thing I couldn't do so far is to verify the content of the POST requests.
Why do I want to do that?
The REST Api I'm developing against has some methods, that require the data objects to be sent in the POST requests body, other methods require the objects to be sent as a FormUrlEncoded data field. So I want to ensure, that the Retrofit interface was set up correctly acc. to the spec.
The following unit test will pass, but the first one sends the data incorrectly inside the body:
//Incorrect
#POST("api/v1/user/senddata")
Observable<Void> senddata (
#Path("VIN") String vin,
#Body PoiWrapper wrappedPoi);
//Correct
#FormUrlEncoded
#POST("api/v1/user/senddata")
Observable<Void> senddata(
#Path("VIN") String vin,
#Field("data") PoiWrapper wrappedPoi);
I know the MockWebServer has the takeRequest() method, but I'm stuck with getting the actual field and data from that requests body.
Thank you for your help!
Try following these examples:
RecordedRequest recordedRequest = server.takeRequest();
assertEquals("POST", recordedRequest.getMethod());
assertEquals("def", recordedRequest.getBody().readUtf8());
assertEquals("3", recordedRequest.getHeader("Content-Length"));
assertEquals("text/plain; charset=utf-8", recordedRequest.getHeader("Content-Type"));

Weblogic clustering configuration

I am developing an application with JDeveloper 11.1.1.6.0. I have a problem with my client application when I try to connect to a weblogic server from a cluster from within my application. A certain service runs on this server that I would like to call.
The situation is as follows:
There is a weblogic instance, whose configuration I cannot change at the moment. The weblogic instance has the following servers and clusters:
Admin server AS - (runs on Machine M1) URL: A, port: 1 - URL for connection t3://A:1
Cluster C containing:
Server S1 - (runs on Machine M1) URL: A, port: 2 - uses Database D1 - URL for connection t3://A:2
Server S2 - (runs on Machine M2) URL: B, port: 1 - uses Database D2 - URL for connection t3://B:1
Server S3 - (runs on Machine M2) URL: B, port: 2 - uses Database D2 - URL for connection t3://B:2
I am trying to connect to t3://A:2 and not to the cluster or any of the other two servers. However, it works only every third time, maybe because of the three servers within the cluster. The cluster uses unicast for messaging and round-robin-affinity for load balancing.
I am trying to find out what causes this. Can I change something within the configuration of the weblogic where my client application runs (integrated or standalone)? Or must the configuration setup of the instance with the server cluster be changed?
Thank you in advance!
Best Regards
(23.05.2013)
EDIT:
We use a plain JNDI-Lookup to access an EJB on the remote server in the described scenario.
Context ctx = new InitialContext();
Object o = ctx.lookup(...)
...
jndi.properties:
java.naming.provider.url=t3://A:2
java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
It seems to be possible to send the JNDI-Request to the right server by setting the property PIN_TO_PRIMARY_SERVER. Yet, subsequent ejb-requests are still routed to the whole cluster using round robin...
Can we do something on client-side to change this behavior to always address the specific server with the url t3://A:2?
I had a similar problem and after trying changing the InvocationContext environment properties, I found that I had very little luck. Instead I had to alter the weblogic-ejb-jar.xml for my stateless session bean.
String destination = "t3://node-alpha:2010";
Hashtable<String, String> env = new Hashtable<String, String>();
env.put( Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put( Context.PROVIDER_URL, destination );
// env.put( weblogic.jndi.WLContext.ENABLE_SERVER_AFFINITY, "true" );
// env.put( weblogic.jndi.WLContext.PIN_TO_PRIMARY_SERVER, "true" );
InitialContext ctx = new InitialContext( env );
EJBHome home = (EJBHome) ctx.lookup( JNDI_REMOTE_SYSTEM_SF );
sf = SomeSf.class.cast( home.getClass().getMethod( "create" ).invoke( home ) );
// Check that we are hitting the right server node.
System.out.println( destination + " => " + sf );
Once you start a transaction, you shouldn't change servers, so I would create a stateless bean to receive the targeted calls and from there begin the work you intend to do. You can set a stateless bean as not clusterable in the weblogic-ejb-jar.xml. You actually need to set both items listed below.
<home-is-clusterable>False</home-is-clusterable>
<stateless-bean-is-clusterable>False</stateless-bean-is-clusterable>
What this means is that when getting a reference through the initial context, is that the targeted server will give an instance of the reference to the stateless bean on that particular cluster node.
Using the servers
node-alpha:2010
node-alpha:2011
node-beta:3010
node-beta:3011
With home-is-clusterable & stateless-bean-is-clusterable set to true
Here the first entry is the server it is targeting, then the rest are for fail-over and/or the load balancing (e.g. round robin).
ClusterableRemoteRef(
3980825488277365621S:node-alpha:[2010,2010,-1,-1,-1,-1,-1]:MyDomain:node-alpha
[
3980825488277365621S:node-alpha:[2010,2010,-1,-1,-1,-1,-1]:MyDomain:node-alpha/338,
4236365235325235233S:node-alpha:[2011,2011,-1,-1,-1,-1,-1]:MyDomain:node-alpha/341,
1321244352376322432S:node-beta:[3010,3010,-1,-1,-1,-1,-1]:MyDomain:node-beta/342,
4317823667154133654S:node-beta:[3011,3011,-1,-1,-1,-1,-1]:MyDomain:node-beta/345
]
)/338
With home-is-clusterable & stateless-bean-is-clusterable set to false
weblogic.rmi.internal.BasicRemoteRef - hostID: '-3980825488277365621S:node-alpha:[2010,2010,-1,-1,-1,-1,-1]:MyDomain:node-alpha', oid: '336', channel: 'null'
weblogic-ejb-jar.xml example below.
<weblogic-ejb-jar>
<weblogic-enterprise-bean>
<ejb-name>SomeSf</ejb-name>
<stateless-session-descriptor>
<pool>
<max-beans-in-free-pool>42</max-beans-in-free-pool>
</pool>
<stateless-clustering>
<home-is-clusterable>false</home-is-clusterable>
<stateless-bean-is-clusterable>false</stateless-bean-is-clusterable>
<stateless-bean-methods-are-idempotent>true</stateless-bean-methods-are-idempotent>
</stateless-clustering>
</stateless-session-descriptor>
<transaction-descriptor>
<trans-timeout-seconds>20</trans-timeout-seconds>
</transaction-descriptor>
<enable-call-by-reference>true</enable-call-by-reference>
<jndi-name>SomeSf</jndi-name>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>

Amazon Product API: "Your request is missing a required parameter combination" on Blended ItemSearch

I'm having some problems trying to do an ItemSearch on the Blended index using the Amazon Product API.
According to the documentation, Blended requests cannot specify the MerchantId parameter - and indeed, if I try to include it I get an error telling me so. However, when I don't include it, I get an error telling me that my request is missing a required parameter combination and that a valid combination includes MerchantId... what the hell?
The failing requests are being sent as part of batches with other requests that are succeeding. I'm using REST to send my requests, so here's an example:
http://ecs.amazonaws.com/onca/xml?AWSAccessKeyId=-------------&
ItemSearch.1.Keywords=Mates%20of%20State&
ItemSearch.1.MerchantId=Amazon&
ItemSearch.1.SearchIndex=DVD&
ItemSearch.2.Keywords=teaching%20Lily%20various%20computer%20related%20skills&
ItemSearch.2.SearchIndex=Blended&
ItemSearch.Shared.Availability=Available&
ItemSearch.Shared.Condition=All&
ItemSearch.Shared.ResponseGroup=Small%2CSalesRank%2CImages%2COfferSummary%2CSimilarities&
Operation=ItemSearch%2CSimilarityLookup&
Service=AWSECommerceService&
SimilarityLookup.1.ItemId=B000FNNHZ2&
SimilarityLookup.2.ItemId=B000EQ5UPU&
SimilarityLookup.Shared.Availability=Available&
SimilarityLookup.Shared.Condition=All&
SimilarityLookup.Shared.MerchantId=Amazon&
SimilarityLookup.Shared.ResponseGroup=Small%2CSalesRank%2CImages%2COfferSummary&
Timestamp=2010-04-02T17%3A18%3A05Z&
Signature=----------------
Here's the XML response:
<Items xmlns="http://webservices.amazon.com/AWSECommerceService/2005-10-05">
<Request>
<IsValid>False</IsValid>
<ItemSearchRequest>
<Availability>Available</Availability>
<Condition>All</Condition>
<Keywords>teaching Lily various computer related skills</Keywords>
<ResponseGroup>Similarities</ResponseGroup>
<ResponseGroup>SalesRank</ResponseGroup>
<ResponseGroup>OfferSummary</ResponseGroup>
<ResponseGroup>Small</ResponseGroup>
<ResponseGroup>Images</ResponseGroup>
<SearchIndex>Blended</SearchIndex>
</ItemSearchRequest>
<Errors>
<Error>
<Code>AWS.MissingParameterCombination</Code>
<Message>Your request is missing a required parameter combination. Required parameter combinations include MerchantId, Availability.</Message>
</Error>
</Errors>
</Request>
</Items>
Any ideas as to what I'm doing wrong?
I seem to have solved this by removing both the Availability and Condition parameters. I'd ideally prefer to be able to filter by availability, but at least it's working.