I have no knowledge of F5 and trying to read these rules. If some one can help me understand them.
Following rules is reading HTTP request and (defining variable INTRSSN?) getting a node and saving it in a persistence table.
when HTTP_REQUEST {
if { ( [HTTP::method] eq "POST") and
( [HTTP::path] equals "/webserv/Interaction") and
( [HTTP::header value "Content-Length"] < 1024 ) }{
#Debugging Purpose
#log local0. "First Request: [HTTP::uri]"
HTTP::collect [HTTP::header Content-Length]
if { [info exists "INTRSSN"] }{
set IntrExist [persist lookup uie $INTRSSN node]
#log local0. "Response check if exist $IntrExist"
if {($IntrExist != "")}{
node $IntrExist
}
}
}
}
This rule will read the HTTP request and extract a specific tag value is put it in INTRSSN variable. This variable will be saved in persistence table.
when HTTP_REQUEST_DATA {
if { ( [HTTP::path] equals "/webserv/Interaction") and
( [HTTP::header value "Content-Length"] < 1024 ) }{
set INTRSSN [findstr [HTTP::payload] "<soap1:sessionID>" 17 "<"]}
if { $INTRSSN != "" } {
#Debugging Purpose
#log local0. "SOAP Session ID: $INTRSSN"
catch { persist uie "$INTRSSN"}
#log local0. "Request_Data $INTRSSN"
}
}
I did not understand this event.
when HTTP_RESPONSE {
if { [HTTP::header "Content-Type" ] equals "text/xml" }{
set resdata [HTTP::payload]
set INTRSSN [findstr $resdata "<sessionID>" 11 "<"]
if { $INTRSSN != "" } {
#Debugging Purpose
#log local0. "Found sessionID on Response: $INTRSSN in SOAP response from: [LB::server addr]"
#log local0. "Interaction $INTRSSN"
catch {persist add uie $INTRSSN 600}
}
}
}
The HTTP_RESPONSE portion attempts to read the XML response and also extract a specific tag value, put it in the $INTRSSN value and save/update a persistence record.
Basically, the whole iRule put together is a way of mapping a specific field within the HTTP body to use for persistence (ensuring the connection goes to the same backend server for the life of the connection).
Related
I'm trying to return a list of my model sorted by date. But I run into a vague error.
Here is my graphql.schema
type Vote #model(timestamps: { createdAt: "created_at", updatedAt: "updated_at" }) {
id: ID!
name: String!
date: AWSTimestamp #index(name: "date-index", sortKeyFields: ["name"], queryField: "getVotesByDate")
}
Here is the request:
Future<List<Vote?>> recentVotes() async {
const getRecentVotes = "getRecentVotes";
String document = """
query getRecentVotes {
listVotes(limit: 5) {
items {
date
id
name
}
nextToken
}
}
""";
try {
final request = GraphQLRequest(
document: document,
modelType: Vote.classType,
decodePath: getRecentVotes,
);
final response = await Amplify.API.query(request: request).response;
List<Vote?>? votes = response.data?.items;
if (votes == null) {
return [];
}
_voteLength = votes.length;
return votes;
} catch (err) {
debugPrint(err.toString());
}
return [];
}
The error I get back is pretty terrible:
flutter: ApiException(message: The HTTP response status code is [400]., recoverySuggestion: The metadata associated with the response is contained in the HTTPURLResponse.
flutter: For more information on HTTP status codes, take a look at
flutter: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes, underlyingException: null)
As best I can tell, it's just a standard bad request error but with no message of what makes it bad. The graphql syntax is valid and tested.
*Edit
I've managed to restart the app which provided more details about the error. With the same code, I now get
flutter: type 'Null' is not a subtype of type 'String'
My first thought after this is that there's some returned field that is null that cannot be. I've checked the name and the id of all the records in the database and they are not null so I'm not sure how that's possible.
I have a script groovy, this script for live fetching of docker image,
I want to add the authentication function with the private repository, but I am not familiar with groovy, who can help me, thanks
import groovy.json.JsonSlurper
// Set the URL we want to read from, it is MySQL from official Library for this example, limited to 20 results only.
docker_image_tags_url = "https://registry.adx.abc/v2/mysql/tags/list"
try {
// Set requirements for the HTTP GET request, you can add Content-Type headers and so on...
def http_client = new URL(docker_image_tags_url).openConnection() as HttpURLConnection
http_client.setRequestMethod('GET')
// Run the HTTP request
http_client.connect()
// Prepare a variable where we save parsed JSON as a HashMap, it's good for our use case, as we just need the 'name' of each tag.
def dockerhub_response = [:]
// Check if we got HTTP 200, otherwise exit
if (http_client.responseCode == 200) {
dockerhub_response = new JsonSlurper().parseText(http_client.inputStream.getText('UTF-8'))
} else {
println("HTTP response error")
System.exit(0)
}
// Prepare a List to collect the tag names into
def image_tag_list = []
// Iterate the HashMap of all Tags and grab only their "names" into our List
dockerhub_response.results.each { tag_metadata ->
image_tag_list.add(tag_metadata.name)
}
// The returned value MUST be a Groovy type of List or a related type (inherited from List)
// It is necessary for the Active Choice plugin to display results in a combo-box
return image_tag_list.sort()
} catch (Exception e) {
// handle exceptions like timeout, connection errors, etc.
println(e)
}
The problem has been resolved, thank you everyone for your help
// Import the JsonSlurper class to parse Dockerhub API response
import groovy.json.JsonSlurper
// Set the URL we want to read from, it is MySQL from official Library for this example, limited to 20 results only.
docker_image_tags_url = "https://registry.adx.vn/v2/form-be/tags/list"
try {
// Set requirements for the HTTP GET request, you can add Content-Type headers and so on...
def http_client = new URL(docker_image_tags_url).openConnection() as HttpURLConnection
http_client.setRequestMethod('GET')
String userCredentials = "your_user:your_passwd";
String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userCredentials.getBytes()));
http_client.setRequestProperty ("Authorization", basicAuth);
// Run the HTTP request
http_client.connect()
// Prepare a variable where we save parsed JSON as a HashMap, it's good for our use case, as we just need the 'name' of each tag.
def dockerhub_response = [:]
// Check if we got HTTP 200, otherwise exit
if (http_client.responseCode == 200) {
dockerhub_response = new JsonSlurper().parseText(http_client.inputStream.getText('UTF-8'))
} else {
println("HTTP response error")
System.exit(0)
}
// Prepare a List to collect the tag names into
def image_tag_list = []
// Iterate the HashMap of all Tags and grab only their "names" into our List
dockerhub_response.tags.each { tag_metadata ->
image_tag_list.add(tag_metadata)
}
// The returned value MUST be a Groovy type of List or a related type (inherited from List)
// It is necessary for the Active Choice plugin to display results in a combo-box
return image_tag_list.sort()
} catch (Exception e) {
// handle exceptions like timeout, connection errors, etc.
println(e)
}
here is the result
I'm trying to do some serverside validation in grails and pass my errors back to the frontend as json to be processed by angularjs.
Error conditions
Department - required
Department - unique
Description - foobar not allowed
I have the following code.
Controller
def saveDepartment() {
def errors = []
def success = true
def department
try{
department = departmentService.save(request.JSON);
if(department.hasErrors()) {
success = false
errors = department.errors.fieldErrors;
}
} catch(Exception e){
e.printStackTrace()
errors = "Unknown"
success = false
if(log.errorEnabled){
log.error("save department encountered unknown error: ", e)
}
response.status = 500
} finally {
respond ([success:success, errors:errors, department:department]) as JSON;
}
}
Service
def save(jsonObj) {
def dept = new Department();
dept.setName(jsonObj.name);
dept.setDescription(jsonObj.description);
if(dept.description.equals('foobar')) {
dept.errors.rejectValue('description', 'foobar', 'Foobar is not allowed')
}
if (!dept.save()) {
dept.discard();
}
return dept;
}
Service Method Attempt 2 with debugging code
def save(jsonObj) {
def dept = new Department();
dept.setName(jsonObj.name);
dept.setDescription(jsonObj.description);
if(dept.description.equals('foobar')) {
println 'rejected value '
dept.errors.rejectValue('description', 'foobar', 'Foobar is not allowed')
}
println 'dept errors ' + dept.errors.allErrors.size();
if (dept.errors.hasErrors()) {
dept.errors.allErrors.each {FieldError error ->
println error
}
}
if (!dept.save(true)) {
println 'dept errors 2 ' + dept.errors.allErrors.size();
if (dept.errors.hasErrors()) {
dept.errors.allErrors.each {FieldError error ->
println error
}
}
}
return dept;
}
Output
..................rejected value
dept errors 1
Field error in object 'org.hri.leaverequest.Department' on field 'description': rejected value [foobar]; codes [foobar.org.hri.leaverequest.Department.descripti
on,foobar.description,foobar.java.lang.String,foobar]; arguments []; default message [Foobar is not allowed]
dept errors 2 1
Field error in object 'org.hri.leaverequest.Department' on field 'name': rejected value [null]; codes [org.hri.leaverequest.Department.name.nullable.error.org.h
ri.leaverequest.Department.name,org.hri.leaverequest.Department.name.nullable.error.name,org.hri.leaverequest.Department.name.nullable.error.java.lang.String,or
g.hri.leaverequest.Department.name.nullable.error,department.name.nullable.error.org.hri.leaverequest.Department.name,department.name.nullable.error.name,depart
ment.name.nullable.error.java.lang.String,department.name.nullable.error,org.hri.leaverequest.Department.name.nullable.org.hri.leaverequest.Department.name,org.
hri.leaverequest.Department.name.nullable.name,org.hri.leaverequest.Department.name.nullable.java.lang.String,org.hri.leaverequest.Department.name.nullable,depa
rtment.name.nullable.org.hri.leaverequest.Department.name,department.name.nullable.name,department.name.nullable.java.lang.String,department.name.nullable,nulla
ble.org.hri.leaverequest.Department.name,nullable.name,nullable.java.lang.String,nullable]; arguments [name,class org.hri.leaverequest.Department]; default mess
age [Property [{0}] of class [{1}] cannot be null]
Issues
If department is null and description has foobar with rejectValue, only one error, "department null" is returned, foobar does not appear in the errors.
If department contains existing value and description contains foobar, the unique constraint is returned but foobar does not appear in the errors.
If department has a good value and foobar still exist, the rejectValue doesn't prevent the save from happening and no errors are thrown. Now if I output dept.errors after the rejectValue, I can see the error actually exist.
Goal
My goal is to return all my errors and not save to the db if an error exist, what am I missing to achieve that goal?
You can do it this way:
dept.validate()
if(dept.description.equals('foobar')) {
dept.errors.rejectValue('description', 'foobar', 'Foobar is not allowed')
}
if(!dept.errors.hasErrors()) {
dept.save()
}
return dept
surely that is the validation constraints that you need to get right in the domain class or relevant validator?.
You have a set of criterias and the validation on the backend should fail to match what you expect to return or not as an error ? or maybe I am missing something
class Example {
Department deparment
static constraints = {
department(nullable:false, blank:false, unique:true, validator: checkDept)
}
static def checkDept= { val, obj, errors ->
//department has a value
if (val) {
//val is now also the same as object.department
if (obj.deparment.description='foo') {
errors.rejectValue(propertyName, "nullable.input", [''] as Object[], 'this is description as foo being rejected')
} else if (obj.deparment.name='bar') {
errors.rejectValue('department.name', "nullable.input", [''] as Object[], 'this is name of bar')
} else {
errors.rejectValue(propertyName, "nullable.input", [''] as Object[], 'this is null and being rejected')
}
}
}
}
propertyName will bind to actual object name - if you are failing based on department.something and the field names are that on the gsp page then you may need to tweak that.
The logics of above is not exactly what you have asked for but it should give you an idea of how you can customise to exactly what you wish to fail. If it doesn't match those then it will just go through as you require
What is the difference between Request.CreateResponse(HttpStatusCode.OK) and
Request.CreateResponse(HttpStatusCode.OK, object) in ASP.NET Web API?
If the model corresponding to object does not have a status, is it not going to set the HttpStatusCode to true or false?
I have come to this question because of the following scenario
public HttpResponseMessage Put(int id, ModelObject object)
{
if (ModelState.IsValid && id == object.objectID)
{
db.Entry(object).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
**if i check httpresponsemessage.statuscode it shows httpresponsemessage is null in the calling method even if the line executes
Task response = httpClient.PutAsJsonAsync(uri, modelObject);
return JsonConvert.DeserializeObjectAsync<HttpResponseMessage>(response.Result.Content.ReadAsStringAsync().Result).Result;
is this is correct
Request.CreateResponse(HttpStatusCode.OK)
create only a response with httpStatusCode
Request.CreateResponse(HttpStatusCode.OK,"this test message")
create a response with httpStatusCode associated with HTTPResponseMessage
According to your phrasing, you seem to be confusing metadata and payload.
The status line and headers of an HTTP message describe what's going on on the HTTP level, so a client application ("user agent") knows how to interpret the response.
Then there's the payload, that which the server wishes to return to the client. While the headers describe the payload, the payload has no influence whatsoever on the HTTP side of things.
The following repsonse is entirely valid:
HTTP/1.1 404 Not Found
...
{
"found" : "true"
}
And so is the following:
HTTP/1.1 200 OK
...
{
"status" : "error"
}
WebAPI is not going to look at your payload to determine the status code (because there is no relation between the two whatsoever), so you can specify the response code and its payload separately.
For example I would like to send the users score to the database and instead of it returning the typical status, id and rev I would like it to return the users rank. I'm guessing this isn't possible but figured I would ask.
The response to an HTTP POST/PUT should really only be used to help you confirm that it succeeded.
I'm even struggling to see even how you can get the rank of a user returned by a couchdb view, unless you retrieve the data for all users and work out the position of your user.
This use case ...
Simple structured data clearly tabular
The requirement to respond fast to a numerical column (Method to calculate the rank for a score)
OR the requirement to trigger an update a score table each time a rank is submitted.
... very much smells like a classical case where you may want to use a relational DB.
If the result can be calculated from the document you are to change with your http request, then you can use an update handler to PUT a change to the document and return that result:
// 'myhandler' update function
function(doc, req) {
// create a shorthand for json reponses
var json_reponse = function(obj, code) {
return {
headers: { 'Content-Type': 'application/json' }
, body: JSON.stringify(obj)
, code: code
}
}
// assume the incoming body is json and parse it
// needs proper error handling still
var body = JSON.parse(req.body)
// doc is the user document we are patching
// return an error if it isn't there
if(!doc)
return [null, json_response({error: 'user document not found'}, 404)]
// return an error if new_score is missing from body
if(!body.new_score)
return [null, json_response({error: 'missing property new_score'}, 400)
// now patch the user doc
doc.score = body.new_score
// calculate the new rank depending on your own method
var my_rank = my_rank_function(doc.score, Math.PI, 'bananarama')
return [doc, json_response({success: true, rank: my_rank}, 200)
}
Now PUT new data to receive the new rank:
request(
{ method: 'PUT'
, url: httptp://127.0.0.1:5984/mydb/_design/myddoc/_update/myhandler/myuserdocid
, json: {"new_score": 42}
, headers: { "Content-Type: application/json" }
}
, function(err, response, body) {
console.log("user's new rank:", JSON.parse(body).rank)
}
)
should print user's new rank: LEVEL 11 EIGHTIES GIRL GROUP LEADER
nb: I'm not at work so cannot confirm the code works, but you should get the hang of it...