IOWebSocketChannel Flutter & GraphQL Apollo - flutter

I'm having an issue connecting to a GraphQL endpoint using Web-sockets.
The issues are noted in the comments. I cannot get this working. It works on the browser (separate test application) so the server is fine.
IOWebSocketChannel? _channel;
StreamSubscription? _getSubscription;
connectToWebsocket(BuildContext context) {
// Nothing to listen to. Auth users only.
final auth = authProviderRead(context);
if (auth.modelUser == null) {
return;
}
_channel?.sink.close();
_getSubscription?.cancel();
final headers = {
"Authorization": auth.jwt ?? "",
"Content-Type": "application/json",
};
_channel = IOWebSocketChannel.connect(
Uri.parse(getWebStockUrl()),
headers: headers,
protocols: ["graphql-ws"],
);
// Fails: Just fires "onDone"
// _channel?.sink.add(jsonEncode({"data": subscriptionQuery}));
// Fails with {"type":"connection_error","payload":{"message":"Cannot read properties of undefined (reading 'Authorization')"}}
// _channel?.sink.add(json.encode({"type": "connection_init"}));
// Fails with {"type":"error","payload":{"message":"Invalid message type!"}}
// _channel?.sink.add(jsonEncode(
// {
// "type": "data",
// "query": subscriptionQuery,
// },
// ));
_getSubscription = _channel!.stream.listen((message) {
// Is never fired?
if (kDebugMode) {
print("Got live message");
print(message);
}
// channel!.sink.add('received!');
// channel!.sink.close();
})
..onData((data) {
if (kDebugMode) {
print("onData - WebSocket");
print(data);
}
})
..onDone(() {
if (kDebugMode) {
print("onDone - WebSocket");
}
})
..onError((e) {
if (kDebugMode) {
print("onError - WebSocket");
print(e);
}
});
}
const subscriptionQuery = r'''
subscription Subscription {
gotChatMessage {
messageResults {
message {
markdown
}
}
}
}
''';

I figure it out, there are some additional things that it requires.
From https://github.com/apollographql/subscriptions-transport-ws/blob/master/src/message-types.ts
_channel?.sink.add(jsonEncode({
"type": "connection_init",
"payload": {"Authorization": auth.jwt}
}));
_channel?.sink.add(jsonEncode({
"type": "start",
"payload": {"query": subscriptionQuery}
}));

Related

How do I use Axios GET Params using a search input

I'm trying to send GET request and I also want to fetch the data using the search input. So I have used Params but it is not working ,
here's my code :
// setFetching(true)
let url = `${TEST_API_URL}/teammember/getAll`
try {
const posts: any = await axios.get(`${url}`, {
withCredentials: true,
headers: {
Authorization: `${localStorage.getItem('access_token')}`,
},
params: {
search
},
})
console.log(posts.data.Data)
setPosts(posts.data.Data)
} catch (error: any) {
toast.error('Something went wrong')
}
// setFetching(false)
}, [search])
useEffect(() => {
async function fetchData() {
await fetchFunction()
}
void fetchData()
}, [fetchFunction])```
I recommend you to do like this.
// setFetching(true)
let url = `${TEST_API_URL}/teammember/getAll`
try {
const posts: any = await axios.get(`${url}?search=${search}`, {
withCredentials: true,
headers: {
Authorization: `${localStorage.getItem('access_token')}`,
}
})
console.log(posts.data.Data)
setPosts(posts.data.Data)
} catch (error: any) {
toast.error('Something went wrong')
}
// setFetching(false)
}, [search])
useEffect(() => {
async function fetchData() {
await fetchFunction()
}
void fetchData()
}, [fetchFunction])```

SafeSearch (Google Cloud API) request not returning anything in flutter app

When users upload a photo in my flutter app I want to call the function below to flag inappropriate images. I first upload the image to firebase storage then call this function using the generated image URL. For now, I just want it to print the results to make sure it works but nothing is printed.
static void isAppropriate(String url) async {
const String safeSearchURl =
"https://vision.googleapis.com/v1/images:annotate";
const apiKey = "HIDDEN";
var headers = {
'Content-Type': 'application/json',
'Authorization': 'key=$apiKey'
};
var request = http.Request('POST', Uri.parse(safeSearchURl));
request.body = '''
{
"requests": [
{
"image": {
"source": {
"imageUri": "$url"
}
},
"features": [
{
"type": "SAFE_SEARCH_DETECTION"
}
]
}
]
}''';
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
} else {
print(response.reasonPhrase);
}
}
}
This is an example of what the printed response should be:
{
"responses": [
{
"safeSearchAnnotation": {
"adult": "UNLIKELY",
"spoof": "VERY_UNLIKELY",
"medical": "VERY_UNLIKELY",
"violence": "LIKELY",
"racy": "POSSIBLE"
}
}
]
}

capacitor community/http handle errors

I often use Axios to perform requests in my applications, however due to incompatibility with iphone, I had to use the capacitor-community/http library, however the try catch blocks are always returning success, even if there was an error in the request. How can I handle errors using this library?
try {
await Requester.auth.public.login(formData);
this.$store.dispatch('login', user);
this.$root.$emit('showToast', {
text: 'Seja bem vindo!',
color: 'success',
});
this.$router.push({ name: 'Cotacao' });
} catch (err) {
this.$root.$emit('showToast', {
text: err.response?.data ?? err.toString(),
color: 'error',
});
} finally {
this.loading.submitForm = false;
}
},
My request
const login = async (formData: AuthLoginFormData): Promise<User> => {
const res: HttpResponse = await Http.post({
url: `${BASE_URL}public/auth/login`,
headers: {
'Content-Type': 'application/json',
},
data: formData,
webFetchExtra: {
credentials: 'include',
},
});
return res.data;
};
Install Latest https://github.com/capacitor-community/http plugin
use function
public async login(formData: AuthLoginFormData){
let options = {
url: `${BASE_URL}public/auth/login`,
headers: {
'Content-Type': 'application/json',
},
data: formData,
webFetchExtra: {
credentials: 'include',
}
};
let response: HttpResponse = await Http.request(options);
if (response.status === 200) {
return Promise.resolve(res);
}
return Promise.reject(response.data);
}

How to receive the response of a POST request using flutter

I am new to flutter and am trying to receive a response that is returned when I do a post request. I want to display the response object in a preview modal however, i am stuck on how to go about it. I have so far been able to hit the post endpoint successfully and a console.log shows me the response as I expected. How can I receive the response and assign it to a variable that I can then pass to a view modal?
Here is what I have done so far:
/* The Post DbRequest */
Future < Reservation ? > priceReservation(Reservation priceReservation) async {
var content = jsonEncode(priceReservation.toJson());
const baseUrl = ApiEndPoint.baseUrl;
searchUrl = '$baseUrl/reservation/price';
var response = await http.post(
Uri.parse(searchUrl),
body: content,
headers: {
"Content-Type": "application/json"
},
);
final data = json.decode(response.body);
if (response.statusCode == 202) {
print(data);
return data;
} else
print(data);
return null;
}
/* The Post Service */
priceReservation(priceReservation) async {
ReservationDbRequests requests = ReservationDbRequests();
Reservation ? reservation =
await requests.priceReservation(priceReservation);
return reservation;
}
/* How can I receive the response in this save method and assign it the data variable */
_save() async {
if (_formKeyBooking.currentState!.validate()) {
Reservation reservationObject = new Reservation(
roomId: _roomController.text,
email: _emailController.text,
quantity: _quantityController.text.toString(),
checkInDate: DateTime.parse(_checkInController.text),
checkOutDate: DateTime.parse(_checkOutController.text),
);
Response data = await Provider.of < BookingService > (context, listen: false)
.priceReservation(reservationObject);
print(data);
setState(() {
_isLoading = false;
});
toastMessage(ToasterService.successMsg);
} else {
toastMessage(ToasterService.errorMsg);
}
}
// Here is my response
{
"id": "c204b78b-cae3-44ea-9aaf-2f439488fef9",
"email": "adeleke#email.com",
"quantity": 1,
"nights": 5,
"totalPricePerRoomPerNight": 134.07,
"totalPrice": {
"rooms": 615.0,
"discounts": 0.0,
"taxes": 55.35,
"total": 670.35
},
"room": {
"id": "d54986a8-4e00-4332-8edc-acf6e380f6c4",
"name": "villa",
"price": 123.0
},
"checkInDate": "2021-09-29T12:00:00+03:00",
"checkOutDate": "2021-10-04T12:00:00+03:00",
"taxes": [
{
"name": "room services",
"percent": 9.0,
"amount": 11.07
}
],
"discounts": []
}
will this help? check this artilcle for json serilization for complex response
Future <Map<String,dynamic>?> priceReservation(Reservation priceReservation) async {
//you API access code goes here
//check the status first before decoding
if (response.statusCode == 200) { //got the response with data
return json.decode(response.body);
} else if (response.statusCode == 204) { //got the response but no data
return null;
} else { //throw exception for other status code
throw 'error';
}
}
/* The Post Service */
Future<Map<String,dynamic>?> priceReservation(priceReservation) async {
ReservationDbRequests requests = ReservationDbRequests();
Map<String,dynamic>? response =
await requests.priceReservation(priceReservation);
return response;
}
//view
Map<String,dynamic>?> response = await Provider.of < BookingService > (context, listen: false)
.priceReservation(reservationObject);
print(response); //now it should be a Map
if(response != null){
print(response); //all response
print(response['id']); //access id
print(response['email']); //access email
print(response['room']['name']); //access room name
}

401 error accessing Cloudant from IBM Cloud Function

I have created a Cloudant service and credentials (1) along with a database and a couple of documents. I want to access that database from an IBM Cloud Function so created a function to do that. I tested the function by adding the copied and pasted credentials from (1) into the "Invoke with credentials" box (along with the and the db name and a valid docid). The function seems to take all that info correctly but I get a 401 error... any help would be massively appreciated!
{
"error": {
"description": "couch returned 401",
"errid": "non_200",
"error": "unauthorized",
"headers": {
"cache-control": "must-revalidate",
"content-type": "application/json",
"date": "Sat, 30 May 2020 16:37:25 GMT",
"statusCode": 401,
"strict-transport-security": "max-age=31536000",
"uri": "xxxxxxx",
"via": "1.1 lb1.bm-cc-eu-gb-04 (Glum/1.89.6)",
"www-authenticate": "Basic realm=\"Cloudant Private Database\"",
"x-cloudant-action": "cloudantnosqldb.any-document.read",
"x-cloudant-backend": "bm-cc-eu-gb-04",
"x-cloudant-request-class": "lookup",
"x-content-type-options": "nosniff",
"x-couch-request-id": "03e7fe91bb"
},
"message": "_reader access is required for this request",
"name": "Error",
"reason": "_reader access is required for this request",
"request": {
"headers": {
"accept": "application/json",
"content-type": "application/json"
},
"method": "GET",
"uri": "xxxxx"
},
"scope": "couch",
"stack": "Error: _reader access is required for this request\n at Object.clientCallback (/node_modules/#cloudant/cloudant/node_modules/nano/lib/nano.js:151:15)\n at Request._callback (/node_modules/#cloudant/cloudant/lib/clientutils.js:162:11)\n at Request.self.callback (/node_modules/request/request.js:185:22)\n at Request.emit (events.js:198:13)\n at Request.self._source.emit (/node_modules/#cloudant/cloudant/lib/eventrelay.js:78:21)\n at Request.<anonymous> (/node_modules/request/request.js:1161:10)\n at Request.emit (events.js:198:13)\n at Request.self._source.emit (/node_modules/#cloudant/cloudant/lib/eventrelay.js:78:21)\n at IncomingMessage.<anonymous> (/node_modules/request/request.js:1083:12)",
"statusCode": 401
}
}
The function code is as follows:
/**
* Read a document in Cloudant database:
* https://docs.cloudant.com/document.html#read
**/
function main(message) {
var cloudantOrError = getCloudantAccount(message);
if (typeof cloudantOrError !== 'object') {
return Promise.reject(cloudantOrError);
}
var cloudant = cloudantOrError;
var dbName = message.dbname;
var docId = message.docid || message.id;
var params = {};
if (!dbName) {
return Promise.reject('dbname is required.');
}
if (!docId) {
return Promise.reject('docid is required.');
}
var cloudantDb = cloudant.use(dbName);
if (typeof message.params === 'object') {
params = message.params;
} else if (typeof message.params === 'string') {
try {
params = JSON.parse(message.params);
} catch (e) {
return Promise.reject('params field cannot be parsed. Ensure it is valid JSON.');
}
}
return readDocument(cloudantDb, docId, params);
}
function readDocument(cloudantDb, docId, params) {
return new Promise(function (resolve, reject) {
cloudantDb.get(docId, params, function (error, response) {
if (!error) {
resolve(response);
} else {
console.error('error', error);
reject(error);
}
});
});
}
function getCloudantAccount(params) {
var Cloudant = require('#cloudant/cloudant');
var cloudant;
if (!params.iamApiKey && params.url) {
cloudant = Cloudant(params.url);
} else {
checkForBXCreds(params);
if (!params.host) {
return 'Cloudant account host is required.';
}
if (!params.iamApiKey) {
if (!params.username || !params.password) {
return 'You must specify parameter/s of iamApiKey or username/password';
}
}
var protocol = params.protocol || 'https';
if (params.iamApiKey) {
var dbURL = `${protocol}://${params.host}`;
if (params.port) {
dbURL += ':' + params.port;
}
cloudant = new Cloudant({
url: dbURL,
plugins: {iamauth: {iamApiKey: params.iamApiKey, iamTokenUrl: params.iamUrl}}
});
} else {
var url = `${protocol}://${params.username}:${params.password}#${params.host}`;
if (params.port) {
url += ':' + params.port;
}
cloudant = Cloudant(url);
}
}
return cloudant;
}
function checkForBXCreds(params) {
if (params.__bx_creds && (params.__bx_creds.cloudantnosqldb || params.__bx_creds.cloudantNoSQLDB)) {
var cloudantCreds = params.__bx_creds.cloudantnosqldb || params.__bx_creds.cloudantNoSQLDB;
if (!params.host) {
params.host = cloudantCreds.host || (cloudantCreds.username + '.cloudant.com');
}
if (!params.iamApiKey && !cloudantCreds.apikey) {
if (!params.username) {
params.username = cloudantCreds.username;
}
if (!params.password) {
params.password = cloudantCreds.password;
}
} else if (!params.iamApiKey) {
params.iamApiKey = cloudantCreds.apikey;
}
}
}
Basically, copying and pasting those credentials led to it not working. Not sure why. To get a test invocation working I added url, docid, dbname, host, url and iamApiKey values to the parameters section of the function. That worked.