I'm trying to use Apache XMLRPC to manage posts at a small weblog service. The support isn't great there and they can't really help. They say the weblog supports the metaweblog api.
I'm trying to retrieve all my posts using the rpc "metaWeblog.getPost":
token = client.invoke("metaWeblog.getPost", new Object[] {123, // also tried "123" and "\"123\""
"username",
"password"});
When I use 123 (no quotes), I get this response: java.lang.Exception: java.lang.Integer cannot be cast to java.lang.String
When I use "123" or "\"123\"" (quotes), I get this response: java.lang.Exception: Invalid postid format: 123
This code does work with my Wordpress weblog's.
Wordpress probably works because it is in PHP and isn't as type sensitive as java.
The docs for metaWeblog say that the raw xml representation of a request looks like this:
<?xml version="1.0"?>
<methodCall>
<methodName>metaWeblog.getPost</methodName>
<params>
<param>
<value><i4>1829</i4></value>
</param>
<param>
<value>Bull Mancuso</value>
</param>
<param>
<value><base64>bm93YXk=</base64></value>
</param>
</params>
</methodCall>
So you need to try establishing the params as variables of the right type
The postId needs to be a 32 big integer, the password is base64 encoded, the username is a string.
Declare your variables properly and pass variables, not quoted constants, to the invoke method.
Then, the xml that is formed under the hood by the rpc library will make sure that <i4></i4> is around the post id, etc.
Hope this helps a little. At the very least, you can prove that the other side isn't properly implementing metaWeblog. At best, you've solved your problem and can keep moving.
Related
I found a very strange behavior in spring rest.
Having an endpoint like the following
#GetMapping("/foo")
public String foo() {
return "bar";
}
returns the value bar. Sounds correct, but this is not a valid json, the effective result should be "bar" (note the ""). One might argue that spring expects that if a method returns a string, you have already manually serialized the object, but if all other objects are serialized by spring, then i would expect to have a special way to tell that its already serialized but the default way should be to serialize the value.
Maybe i'm missing something here, that's the reason why i didn't created a ticket in the spring issue tracker jet.
Unregistering the StringHttpMessageConverter as described in this answer should do the trick: https://stackoverflow.com/a/37906098/505621
While not really an answer, there are 2 possible workarounds:
Encode it yourself
Just add the required quotation mark explicitly to the response string \".
This could for example be done by using JSONObject.quote(yourString).
Wrapping
Wrap your string into a simple object or custom class. Then Jackson knows what to do with it.
Collections.singletonMap("value", yourString);
I have a stored proc that returns json. The proc works fine and when I call it in SSMS it returns a json object that I can click and see as valid json. When I call it through Visual Studio it does the same, and clicking into it and pressing return formats it nicely so it's readable (and not all on a single line). If I take the string and pass it back into the sql function IsJson, it also returns true, so I'm 100% confident that the json coming out of the proc is valid.
However, my frontend developer is unable to parse it, and it seems to boil down to something trying to convert it somewhere.
The json (as output from the proc) is:
{"APIResult":[{"ID":200,"Status_Message":"Success","Developer_Message":"Successful login for D56D10AC-3A74-42FC-8BB5-F783A6C0C556 33E4F907-F1E5-4F1B-8CA5-5521291E683A (AppID: (null)).","User_Message":"Successful login","User":[{"ID":"D56D10AC-3A74-42FC-8BB5-F783A6C0C556"}]}]}
Using Postman to hit the live API (or localhost) I get back the data I expect (as above) however, it wraps the entire thing in double quotes and escapes all the double quotes around each element, so I get:
"{\"APIResult\":[{\"ID\":200,\"Status_Message\":\"Success\",\"Developer_Message\":\"Successful login for D56D10AC-3A74-42FC-8BB5-F783A6C0C556 33E4F907-F1E5-4F1B-8CA5-5521291E683A (AppID: (null)).\",\"User_Message\":\"Successful login\",\"User\":[{\"ID\":\"D56D10AC-3A74-42FC-8BB5-F783A6C0C556\"}]}]}"
When I try to parse this in sql (using isjson) it returns false. However, parsing this same code though jsonlint.com interprets it as valid. Trying it through the parser my developer is using http://json.parser.online.fr throws it out as errors too.
At a push, I can tell my developer to strip the first and last characters and replace every \" with " but this seems a bit faffy.
Are there different interpretations of json? I've read that this is often caused by the calling app expecting a string that it needs to json-ify and because it's getting a json object it's json-ifying the json, but even if I force sql server to output the string as a string and not json, it still seems the same. SQL is definitely pushing it out correctly but whatever my developer is calling the api through returns the same format as postman, and doesn't like it. How can I ensure that what the calling code gets is what SQL is giving and not some weird interpretation?
#Tim Try to deserialize the output of stored procedure. Use JSonConvert.Derialize in C#
i'm using camel in a rest context and i've to manipulate a json got from a request . It's something like:
{
'field1':'abc',
'field2':'def'
}
All i've to do is to extract field1 and field2 and put them in 2 properties, so i tried something like that
<setProperty propertyName="Field1">
<jsonpath>$.field1</jsonpath>
</setProperty>
<setProperty propertyName="Field2">
<jsonpath>$.field2</jsonpath>
</setProperty>
but i get this error:
org.apache.camel.ExpressionEvaluationException:
com.jayway.jsonpath.PathNotFoundException: Expected to find an object with property ['field2'] in path $ but found 'java.lang.String'. This is not a json object according to the JsonProvider: 'com.jayway.jsonpath.spi.json.JsonSmartJsonProvider'.
and after some tests i found out my body was empty after the first use of jsonpath.
The same process applied to an XML using xpath doesn't give any error, and i'm wondering if it's possible to do the same with jsonpath instead to create a mapper object in java. thank you in advance
If the processed Camel message is of type InputStream, this stream can obviously be read only once.
To solve this:
either enable Camel stream caching (http://camel.apache.org/stream-caching.html)
or insert a step (before jsonpath queries) in your route to convert message body to a string (so that it can be read multiple times:
(eg <convertBodyTo type="java.lang.String" charset="ISO-8859-1">) )
MarkLogic REST Client API's default search endpoint results in server error when using a query options node that contains more than one extract-path even though the request is successful when either extract-path is used individually within extract-document-data:
{"errorResponse":{"statusCode":500, "status":"Internal Server Error", "messageCode":"RESTAPI-INTERNALERROR", "message":"RESTAPI-INTERNALERROR: (err:FOER0000) Internal error: JSON build, unbalanced pairs: "}}
The offending paths:
<extract-path xmlns:tei="http://www.tei-c.org/ns/1.0" xmlns:FO="http://founders.archives.gov/">/tei:text/FO:metadata/FO:ProjectCode</extract-path>
<extract-path xmlns:tei="http://www.tei-c.org/ns/1.0" xmlns:FO="http://founders.archives.gov/">/tei:text/FO:metadata/FO:ShortProjectTitle</extract-path>
Only occurs when the format is JSON--XML format behaves as expected. This error can be reproduced across disparate datasets.
The entire options node:
<options xmlns="http://marklogic.com/appservices/search">
<search-option>unfiltered</search-option>
<quality-weight>0</quality-weight>
<page-length>10</page-length>
<extract-document-data selected="include">
<extract-path xmlns:tei="http://www.tei-c.org/ns/1.0" xmlns:FO="http://founders.archives.gov/">/tei:text/FO:metadata/FO:ProjectCode</extract-path>
<extract-path xmlns:tei="http://www.tei-c.org/ns/1.0" xmlns:FO="http://founders.archives.gov/">/tei:text/FO:metadata/FO:ShortProjectTitle</extract-path>
</extract-document-data>
</options>
I would simply extract the parent element FO:metadata; however, that returns a string, indicating a dependency on a parsing library (does it not?) which I would rather avoid if possible.
Any suggested workarounds are appreciated. Thanks.
There is a known bug with the inline response that should be fixed in 8.0-3.
In the interim, it should work to get the extracted fragments either as XML or as a multiplepart/mixed response (which, if the source documents are XML would also be XML).
I have a situation where people consuming our API will need to do a partial update in my resource. I understand that the HTTP clearly specifies that this is a PATCH operation, even though people on our side are used to send a PUT request for this and that's how the legacy code is built.
For exemplification, imagine the simple following struct:
type Person struct {
Name string
Age int
Address string
}
On a POST request, I will provide a payload with all three values (Name, Age, Address) and validate them accordingly on my Golang backend. Simple.
On a PUT/PATCH request though, we know that, for instance, a name never changes. But say I would like to change the age, then I would simply send a JSON payload containing the new age:
PUT /person/1 {age:30}
Now to my real question:
What is the best practice to prevent name from being used/updated intentionally or unintentionally modified in case a consumer of our API send a JSON payload containing the name field?
Example:
PUT /person/1 {name:"New Name", age:35}
Possible solutions I thought of, but I don't actually like them, are:
On my validator method, I would either forcibly remove the unwanted field name OR respond with an error message saying that name is not allowed.
Create a DTO object/struct that would be pretty much an extension of my Person struct and then unmarshall my JSON payload into it, for instance
type PersonPut struct {
Age int
Address string
}
In my opinion this would add needless extra code and logic to abstract the problem, however I don't see any other elegant solution.
I honestly don't like those two approaches and I would like to know if you guys faced the same problem and how you solved it.
Thanks!
The first solution your brought is a good one. Some well known frameworks use to implement similar logic.
As an example, latests Rails versions come with a built in solution to prevent users to add extra data in the request, causing the server to update wrong fields in database. It is a kind of whitelist implemented by ActionController::Parameters class.
Let's suppose we have a controller class as bellow. For purpose of this explanation, it contains two update actions. But you won't see it in real code.
class PeopleController < ActionController::Base
# 1st version - Unsafe, it will rise an exception. Don't do it
def update
person = current_account.people.find(params[:id])
person.update!(params[:person])
redirect_to person
end
# 2nd version - Updates only permitted parameters
def update
person = current_account.people.find(params[:id])
person.update!(person_params) # call to person_params method
redirect_to person
end
private
def person_params
params.require(:person).permit(:name, :age)
end
end
Since the second version allows only permitted values, it'll block the user to change the payload and send a JSON containing a new password value:
{ name: "acme", age: 25, password: 'account-hacked' }
For more details, see Rails docs: Action Controller Overview and ActionController::Parameters
If the name cannot be written it is not valid to provide it for any update request. I would reject the request if the name was present. If I wanted to be more lenient, I might consider only rejecting the request if name is different from the current name.
I would not silently ignore a name which was different from the current name.
This can be solved by decoding the JSON body into a map[string]json.RawMessage first. The json.RawMessage type is useful for delaying the actual decoding. Afterwards, a whitelist can be applied on the map[string]json.RawMessage map, ignoring unwanted properties and only decoding the json.RawMessages of the properties we want to keep.
The process of decoding the whitelisted JSON body into a struct can be automated using the reflect package; an example implementation can be found here.
I am not proficient on Golang but I believe a good strategy would be converting your name field to be a read-only field.
For instance, in a strictly object-oriented language as Java/.NET/C++ you can just provide a Getter but not a Setter.
Maybe there is some accessor configuration for Golang just like Ruby has....
If it is read-only then it shouldn't bother with receiving a spare value, it should just ignore it. But again, not sure if Golang supports it.
I think the clean way is to put this logic inside the PATCH handler. There should be some logic that would update only the fields that you want. Is easier if you unpack into a map[string]string and only iterate over the fields that you want to update. Additionally you could decode the json into a map, delete all the fields that you don't want to be updated, re-encode in json and then decode into your struct.