I have different structs for the query in the REST request. I'd like to return HTTP 400: BAD REQUEST when the query string contains an unexpected parameter than my struct.
type FilterData struct {
Filter1 string `form:"filter_1"`
Filter2 string `form:"filter_2"`
Filter3 string `form:"filter_3"`
}
The expected request request is localhost:8000/testing?filter_1=123456&filter_2=test&filter_3=golang
But if the is request like localhost:8000/users?FILTER1=123456&filter_2=test&filter_3=golang or any extra parameter than my expected struct I want to return bad request.
Go gin.Context has c.ShouldBindQuery(&filterData) but this returns the filter_1 as an empty string, indeed in my case that's a bad request.
How would I do an extra check with a common function to all requests?
PS. some values in this struct can be optional.
It is pretty standard in apis to ignore unknown query parameters. If you require some parameters to always have value, use binding:"required" property in your struct tags.
https://github.com/gin-gonic/gin#model-binding-and-validation
If you want to throw back a 400 on unknown query params, you must check contents of c.Request.URL.Query().
Related
I would like a generic function that converts the result of a SQL query to JSON. I would like to build a JSON string manually (or use an external library). For that to happen, I need to be able to enumerate the columns in a row dynamically.
let rows = client
.query("select * from ExampleTable;")
.await?;
// This is how you read a string if you know the first column is a string type.
let thisValue: &str = rows[0].get(0);
Dynamic types are possible with Rust, but not with the tokio-postgres library API.
The row.get function of tokio-postgres is designed to require generic inference according to the source code
Without the right API, how can I enumerate rows and columns?
You need to enumerate the rows and columns, doing so you can get the column reference while enumerating, and from that get the postgresql-type. With the type information it's possible to have conditional logic to choose different sub-functions to both: i) get the strongly typed variable; and, ii) convert to a JSON value.
for (rowIndex, row) in rows.iter().enumerate() {
for (colIndex, column) in row.columns().iter().enumerate() {
let colType: string = col.type_().to_string();
if colType == "int4" { //i32
let value: i32 = row.get(colIndex);
return value.to_string();
}
else if colType == "text" {
let value: &str = row.get(colIndex);
return value; //TODO: escape characters
}
//TODO: more type support
else {
//TODO: raise error
}
}
}
Bonus tips for tokio-postgres code maintainers
Ideally, tokio-postgres would include a direct API that returns a dyn any type. The internals of row.rs already use the database column type information to confirm that the supplied generic type is valid. Ideally a new API uses would use the internal column information quite directly with improved FromSQL API, but a simpler middle-ground exists:-
It would be possible for an extra function layer in row.rs that uses the same column type conditional logic used in this answer to then leverage the existing get function. If a user such as myself needs to handle this kind of conditional logic, I also need to maintain this code when new types are handled by tokio-postgresql, therefore, this kind of logic should be included inside the library where such functionality can be better maintained.
I am trying to compare two jsons, expected and the API Response using Javers, as part of testing. I want the comparison to exclude the ID parameters that are dynamically generated by response.
My VO is like
public class expectedResponse{
#DiffIgnore
private String id;
private String name;
}
Both my expectedResponse- which is read from excel file and the actual response from API are deserialized into this format and then both the responses are compared.
JsonNode expectedOutput = mapper.readTree(expected.toString());
JsonNode apiResponse = mapper.readTree(actual.toString());
diff=javers.compare(expectedOutput, apiResponse);
But this comparison doesn't exclude/ignore the ID field. Any Idea how I can get it to work? I want only the ID field excluded in comparison results, diff in name should be listed.
Also question 2> I am trying to list the changes from diff
if (diff.hasChanges())
{
List<ValueChange> changes=diff.getChangesByType(ValueChange.class);
for (ValueChange change : changes)
{
logger.info(change.getPropertyName()+ "||" +change.getLeft().toString() + "||" +change.getRight().toString());
change.getPropertyName()- doesnt print the property's name but simply prints "_value" as its value.
Can you pls help in identifying what is going wrong with the code and how can I get this fixed? I am not finding much useful documentations about Javers anywhere in google. Any help is appreciated.
You should compare you domain object instead of object with JsonNode class, look that #DiffIgnore annotation is present only in your domain class and there is no connection between JsonNode and ExpectedResponse, thats why Javers doesn't know to ignore this field.
To summarise, your code should looks like this:
ExpectedResponse expectedOutput = ...
ExpectedResponse apiResponse = ...
diff=javers.compare(expectedOutput, apiResponse);
There is an existing question that has much of what I'm after:
Extracting Raw JSON as String inside a Spray POST route
But it stops short without explaining how to get the actual Json string representation out of the Directive[String]. I'm trying to send Json data to Kafka as a string (which the Kafka Producer serializes), so I'm trying to extract the Json in string form. I will do the marshalling to an entity at the other end in the Kafka consumer. The answer link above gets me close:
def rawJson = extract { _.request.entity.asString}
case "value2" => rawJson{ json =>// use the json }
But I end up with Directive[String]. How do I get the String out?
The example you referenced should work. You would use the rawJson directive they defined to wrap your inner route, and the json string would be made available within that inner route.
In the example below, personJson is a String, extracted by the body of the request via the rawJson directive, and made available to the inner route where the rest of the work is done.
def rawJson = extract { _.request.entity.asString}
val personRoute = {
(post & path("persons")){
rawJson{ personJson =>
onSuccess(personService.addPerson(person)){ personWithId =>
complete(StatusCodes.Created, personWithId)
}
}
}
I came up with the following syntax which accomplishes my need to extract the Json in String form. At first I thought it inefficient that I was unmarshaling and then remarshaling again, but then I realized that this provides a form of immediate Json validation. But there may be more efficient ways to do that.
The API is all Spray. handleWith uses an implicit conversion to the RawWeatherData case class.
path("weather"/"data"/"json") {
handleWith { rawRecord: RawWeatherData =>
val rawJsonStr = rawRecord.toJson.toString
kafkaJsonRecordIngest(rawJsonStr)
rawRecord
}
}
I'm using Apache Wink for implementing REST Services and I can't seem to receive parameters of type array or List. The call is being made from ajax $.post:
$.post(url,
{ param: ['string1', 'param2', 'x', 'etc...etc....etc'],
str2: "str2"},
function(data) {// do something
});
On the server side, Strings and ints are correctly received, but the 'param' parameter is always received empty (not null, but with zero elements), whether the variable is defined as String[], List, Set, ... . The receiving function is defined as:
#POST #Produces("application/json") #Path("eee")
public Response eee(#FormParam("str1") String str1, #FormParam("param") String[] param, #FormParam("str2") String str2)
While debugging, I can see a context variable with a table entry like:
wink.formParameters=[param%5B%5D=string1,param%5B%5D=param2,param%5B%5D=x,param%5B%5D=etc...etc....etc,str2=str2]
That translates to 'param[]=string1, param[]=param2, ..', no indexation. Don't know if that's correct.
Any ideas ?
I realize this is an old question, but I had a similar problem, and I ended up fixing it by adding [] to the end of the FormParam name.
So instead of having #FormParam("param"), you would have #FormParam("param[]")
Note that I am also using jQuery's $.params method to serialize my data, but I it looks like your debugging revealed a properly-encoded form string, so I'm suspecting it's just the [] that are missing.
This works for me when I define the accepting variable as :
#FormParam("paramName") List<String> paramList;
You might also need to tweak the client call like:
$.post(url,
{ paramName: "string1",
{ paramName: "string2",
{ paramName: "string3",
str2: "str2"},
function(data) {// do something
});
I'm implementing a search box using CodeIgniter, but I'm not sure about how I should pass the search parameters through. I have three parameters: the search string; product category; and the sort order. They're all optional. Currently, I'm sending the parameters through $_POST to a temporary method, which forwards the parameters to the regular URI form. This works fine. I'm using a weird URI format though:
http://site.com/products/search=computer,sort=price,cat=laptop
Does anyone have a better/cleaner format of passing stuff through?
I was thinking of passing it into the products method as arguments, but since the parameters are optional things would get messy. Should I suck it up, and just turn $_GET methods on? Thanks in advance!
Query Strings
You can enable query strings in CodeIgniter to allow a more standard search function.
Config.php
$config['enable_query_strings'] = FALSE;
Once enabled, you can accept the following in your app:
http://site.com/products/search?term=computer&sort=price&cat=laptop
The benefit here is that the user will find it easy to edit the URL to make a quick change to their search, and your search uses common search functionality.
The down side of this approach is that you are going against one of the design decisions of the CodeIgniter development team. However, my personal opinion is that this is OK provided that query strings are not used for the bulk of your content, only for special cases such as search queries.
A much better approach, and the method the CI developers intended, is to add all your search parameters to the URI instead of a query string like so:
http://site.com/products/search/term/computer/sort/price/cat/laptop
You would then parse all the URI segments from the 3rd segment ("term") forward into an array of key => value pairs with the uri_to_assoc($segment) function from the URI Class.
Class Products extends Controller {
...
// From your code I assume you are calling a search method.
function search()
{
// Get search parameters from URI.
// URI Class is initialized by the system automatically.
$data->search_params = $this->uri->uri_to_assoc(3);
...
}
...
}
This would give you easy access to all the search parameters and they could be in any order in the URI, just like a traditional query string.
$data->search_params would now contain an array of your URI segments:
Array
(
[term] => computer
[sort] => price
[cat] => laptop
)
Read more about the URI Class here: http://codeigniter.com/user_guide/libraries/uri.html
If you're using a fixed number of parameters, you can assign a default value to them and send it instead of not sending the parameter at all. For instance
http://site.com/products/search/all/somevalue/all
Next, in the controller you can ignore the parameter if (parameter == 'all'.)
Class Products extends Controller {
...
// From your code I assume that this your structure.
function index ($search = 'all', $sort = 'price', $cat = 'all')
{
if ('all' == $search)
{
// don't use this parameter
}
// or
if ('all' != $cat)
{
// use this parameter
}
...
}
...
}