Can you tell me where I'm wrong? When I use the Postman then it's working.But why I cannot do the same using Angular2? Here the backend api is from PHP.I have never used PHP backend before.Is that different than normal ASP.net Web Api? I mean the way we have to send the parameters and all...
Service.ts
import { Injectable } from '#angular/core';
import { Http, RequestOptions, Headers, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
#Injectable()
export class AuthenticationData {
authenticationEndPoint: string = "https://www.myk.com/admin/index.php?route=api/login";
constructor(public http: Http) {
}
//to login
loginUser(username: string, password: string): Observable<any> {
let headers = new Headers();
headers.append('content-type', 'application/json');
/*let body = {
username: username,
password: password,
}*/ Not working this too :(
let body='username=myname&password=admin';//I tried hardcode value.But not working
let options = new RequestOptions({ headers: headers });
return this.http.post(this.authenticationEndPoint, body, options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || {};
}
private handleError(error: Response | any) {
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
login.ts
//to login
loginUser(): void {
if (this.loginForm.valid) {
this.authenticationData.loginUser(this.loginForm.value.username, this.loginForm.value.password).subscribe(
data => {
this.response = data;
},
err => {
console.log(err);
},
() => console.log('Complete')
);
}
}
Error:
body: "{"error":"Invalid Request type","status":"201"}", status: 200,
ok: true, statusText: "OK",
Php:
<?php
class ControllerApiLogin extends Controller {
private $error = array();
public function index() {
$json = array();
if (($this->request->server['REQUEST_METHOD'] == 'POST') && !empty($this->request->get['username']) && !empty($this->request->get['password'])) {
if(!empty($this->request->get['username']) && !empty($this->request->get['password'])){
$this->load->language('common/login');
$this->document->setTitle($this->language->get('heading_title'));
// User
$this->registry->set('user', new Cart\User($this->registry));
if ($this->validate()) {
$token = token(32);
$token_count = $this->user->getUniqueToken($token);
if($token_count==0)
{
$this->session->data['token'] = $token;
}else{
$token = token(32);
$token_count = $this->user->getUniqueToken($token);
$this->session->data['token'] = $token;
}
$this->load->model('user/user');
$user_info = $this->model_user_user->getUserByEmail($this->request->get['username']);
$tokeninfo = array();
if(count($user_info) > 0){
$tokeninfo = array(
'token' => $token,
'user_id' => $user_info['user_id'],
'ip' => $this->request->server['REMOTE_ADDR']
);
$date_expired = $this->model_user_user->addUserapitoken($tokeninfo);
}else{
$date_expired = '';
}
$json['token'] = $token;
$json['date_expired'] = $date_expired;
$json['status'] = '200';
}else{
$json['error'] = "No match for Username and/or Password.";
$json['status'] = '201';
}
}else{
$json['error'] = 'Something Went Wrong!!! <br> PLease Enter Correct Login Credentials!!!';
$json['status'] = '201';
}
//$this->response->addHeader('Content-Type: application/json');
//$this->response->setOutput(json_encode($json));
}
else{
$json['error'] = 'Invalid Request type';
$json['status'] = '201';
}
if (isset($this->request->server['HTTP_ORIGIN'])) {
$this->response->addHeader('Access-Control-Allow-Origin: ' . $this->request->server['HTTP_ORIGIN']);
$this->response->addHeader('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
$this->response->addHeader('Access-Control-Max-Age: 1000');
$this->response->addHeader('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
}
$this->response->addHeader('Content-Type: application/json');
$this->response->addHeader('HTTP/1.1'.$json['status']);
$this->response->setOutput(json_encode($json));
}
protected function validate() {
//$this->registry->set('user', new Cart\User($this->registry));
if (!isset($this->request->get['username']) || !isset($this->request->get['password']) || !$this->user->login($this->request->get['username'], html_entity_decode($this->request->get['password'], ENT_QUOTES, 'UTF-8'))) {
$this->error['warning'] = $this->language->get('error_login');
}
return !$this->error;
}
}
OP's feedback: I have to use it like this.Cheers :)
authenticationEndPoint: string = "https://www.myk.com/admin/index.php?route=api/login&username=";
loginUser(username: string, password: string): Observable<any> {
let headers = new Headers();
headers.append('content-type', 'application/json');
let body = '';
let options = new RequestOptions({ headers: headers });
let url = this.authenticationEndPoint + encodeURI(username) + '&password=' + encodeURI(password);
return this.http.post(url, body, options)
.map(this.extractData)
.catch(this.handleError);
}
Original Answer:
headers.append('content-type', 'application/json');
let body='username=myname&password=admin';//I tried hardcode value.But not working
You seem to be setting content type as json. So your body needs to be set as an object. Do:
let body ={
username:myname,
password:admin
}
And then send the request. It should convert this to json and send.
return this.http.post(this.authenticationEndPoint, body, options)
.map(this.extractData)
.catch(this.handleError);
Seems like you want to use URLSearchParams instead, and send the data as x-www-form-urlencoded instead of JSON. The URLSearchParams will encode the parameters as you have tried when hardcoding, but I think your problem is when you are trying to send it as JSON, send it as x-www-form-urlencoded instead. So try this:
import { URLSearchParams } from '#angular/http';
loginUser(username: string, password: string): Observable<any> {
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
let body = new URLSearchParams();
body.set('username',username);
body.set('password',password)
let options = new RequestOptions({ headers: headers });
return this.http.post(this.authenticationEndPoint, body.toString(), options)
.map(this.extractData)
.catch(this.handleError);
}
//you need to import this
import { Http, Headers, URLSearchParams, Request, RequestOptions, RequestMethod } from '#angular/http';
this.body= {
"username":myname,
"password":admin
} //body is defined here
let headers = new Headers();
headers.append('HeaderKey', headerValue);
let options = new RequestOptions({
method: RequestMethod.Post,
url: this.authenticationData.loginUser(this.loginForm.value.username, this.loginForm.value.password),
body: this.body,
headers: headers
});
//here you are making request
this.http.request(new Request(options))
.map(res => res.json())
.subscribe(data => {
//data is fetched
if(data.code==200){
this.response = data;
}
else{
console.log("some issue with the api response")}
}, err => {
console.log("ERROR!: ", err);
});
May be this way things will work for you
Related
This is how I picked a file from device
onPressed: () async {
FilePickerResult? result =
await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: [
'jpg',
'pdf',
'doc'
],
);
List<File> files = result!.paths
.map((path) => File(path!))
.toList();
context
.read<Dropper>()
.fileCheck(result: result);
myfile = files[0];
},
Then I Converted to Uint8List :
Uint8List imgbytes = await myFile.readAsBytes();
Now I am sending that file to Php database
final url = "http://10.0.2.2:8000/api/addSurvey";
final uri = Uri.parse(url);
final response = await api.post(uri, headers: {
'Authorization': token,
}, body: {
"bill_image": imgbytes
}
It throws error msg like this : type 'Uint8List' is not a subtype of type 'String' in type cast
var url = "http://10.0.2.2:8000/api/addSurvey";
Map<String, String> headers = {"Content-Type": "application/json",
'Authorization': token,};
var request = http.MultipartRequest("POST", Uri.parse(url));
if(_image != null){
var pic = await http.MultipartFile.fromBytes('bill_image', imgbytes , filename: 'photo.jpg');
request.files.add(pic);
}
request.send().then((result) async {
http.Response.fromStream(result).then((response) async {
if (response.statusCode == 200)
{
}
else{
}
return response.body;
});
}).catchError((err) => print('merror : '+err.toString())).whenComplete(()
{
});
Try it using multipart request.
if php is accepting parameter as file type File then you need to send image as multipart request i guess.
var headers = {
'Authorization': 'token'
};
var request = http.MultipartRequest('POST', Uri.parse('http://10.0.2.2:8000/api/addSurvey'));
request.files.add(await http.MultipartFile.fromPath('bill_image', 'path to your file'));
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}
I am trying to create simple login and signup in swift with php mysql in backend. I was following "https://github.com/EMacco/ios-tutorials/tree/yummie-network-connection/Yummie" this project
I get the following error
The response is: {"data":[{"response":"Success","username":"Mohammad Tariq Shamim"}]} Error Response could not be decoded
I am getting response from the server but JSON is not getting decoded. Following is my code
enum Route {
static let baseurl = "http://arabscholar.net/android/"
case login
var description: String {
switch self {
case .login: return "login.php"
}
}
}
struct User: Decodable{ let username: String? let response: String? }
struct ApiResponse<T: Decodable>: Decodable {
let status: Int
let data: T?
let error: String?
}
AppError Swift file
enum AppError: LocalizedError {
case errorDecoding
case unknownError
case invalidUrl
case serverError(String)
var errorDescription: String? {
switch self {
case .errorDecoding:
return "Response could not be decoded"
case .unknownError:
return "Unknown error"
case .invalidUrl:
return "Url invalid"
case .serverError(let error):
return error
}
}
}
Main networking struct file
struct NetworkService {
static let shared = NetworkService()
private init() {}
func signin(username: String, password: String, completion: #escaping(Result<User, Error>) -> Void) {
let params = ["login": "user", "email": username, "password": password]
request(route: .login, method: .post, parameters: params, completion: completion)
}
private func request<T: Decodable>(route: Route, method: Method, parameters: [String: Any]? = nil, completion: #escaping(Result<T, Error>) -> Void) {
guard let request = createRequest(route: route, method: method, parameters: parameters) else {
completion(.failure(AppError.unknownError))
return
}
URLSession.shared.dataTask(with: request) { data, response, error in
var result: Result<Data, Error>?
if let data = data {
result = .success(data)
let responseString = String(data: data, encoding: .utf8) ?? "Could not stringify our data"
print("The response is: (responseString)")
} else if let error = error {
result = .failure(error)
print("The error is " + error.localizedDescription)
}
DispatchQueue.main.async {
self.handleResponse(result: result, completion: completion)
}
}.resume()
}
private func handleResponse<T: Decodable>(result: Result<Data, Error>?, completion: (Result<T, Error>) -> Void) {
guard let result = result else {
completion(.failure(AppError.unknownError))
return
}
switch result {
case .success(let data):
let decoder = JSONDecoder()
guard let response = try? decoder.decode(ApiResponse.self, from: data) else {
completion(.failure(AppError.errorDecoding))
return
}
if let error = response.error {
completion(.failure(AppError.serverError(error)))
return
}
if let decodedData = response.data {
completion(.success(decodedData))
} else {
completion(.failure(AppError.unknownError))
}
case .failure(let error):
completion(.failure(error))
}
}
private func createRequest(route: Route, method: Method, parameters: [String: Any]? = nil) -> URLRequest? {
let urlString = Route.baseurl + route.description
guard let url = urlString.asUrl else {return nil}
var urlRequest = URLRequest(url: url)
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.httpMethod = method.rawValue
if let params = parameters {
switch method {
case .get:
var urlComponent = URLComponents(string: urlString)
urlComponent?.queryItems = params.map { URLQueryItem(name: $0, value: "($1)")}
urlRequest.url = urlComponent?.url
case .post:
let bodyData = try?JSONSerialization.data(withJSONObject: params, options: [])
urlRequest.httpBody = bodyData
}
}
return urlRequest
}
}
My PHP code
$postdata = json_decode( file_get_contents( "php://input" ), TRUE );
//$id = $postdata[ "email" ];
//$name = $postdata[ "password" ];
$result[ 'response' ] = "Success";
$result[ 'username' ] = "Mohammad Tariq Shamim";
// Store values in an array
$returnValue = array( $result );
$array['data'] = $returnValue;
// Send back request in JSON format
echo json_encode( $array );
//echo json_encode( array( 'response' => 'No data found for ' . $_POST[ 'email' ] ) );
I need to know how to pass parameters between angular 7 and a PHP API
import { Injectable } from '#angular/core';
import { HttpClient, HttpParams } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) { }
getUsers() {
return this.http.get('http://localhost/backend/json/data_products.php');
}
getProduct(productId) {
const params = new HttpParams().set('id', productId);
return this.http.get('http://localhost/backend/json/data_product.php/', {params});
}
}
but I got this error
core.js:12584 ERROR HttpErrorResponse {headers: HttpHeaders, status: 200, statusText: "OK
Please refer to Angular doc: https://angular.io/api/common/http/HttpClient#get
get(url: string, options: { headers?: HttpHeaders | { [header:
string]: string | string[]; }; observe?: "body"; params?: Ht...)
It should be like:
this.http.get('http://localhost/backend/json/data_product.php/', { params: params });
in your case.
I think you need to pass header in request like below.May be this is help you.
update(id: number, data: any){
let model = JSON.stringify(data);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this._http.put( 'http://localhost/backend/json/data_product.php/'+id,model, options);
}
I'm trying to do is submit the device IMEI to be inserted into the database.
However, the returned JSON output from the database shows the IMEI as null.
Here's what's been implemented:
Requester
class Requester
{
....
func postRequest(_ url: URL, headers : Dictionary<String,String>?, data: Data?, callback : #escaping (_ response: HTTPResponseWithData) -> Void) -> Void
{
let request = Factory.httpRequest(url, method: "POST", headers: headers, data: data)
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
data, response, error in
print("RESPONSE: \(response)");
})
task.resume()
}
....
}
Factory
class Factory
{
func httpRequest(_ url: URL, method: String, headers: Dictionary<String, String>?, data: Data?) -> URLRequest
{
var request = URLRequest(url: url)
request.httpMethod = method
if headers != nil
{
for (field, value) in headers!
{
request.addValue(value, forHTTPHeaderField: field)
}
}
if data != nil
{
request.httpBody = data
}
return request
}
}
MainVC
let requester = Requester()
#IBAction func sendRequest(_ sender: Any)
{
var json: Dictionary<String, Any> = [:]
json["imei"] = myIMEI
do
{
let data = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
post(theData: data)
}
catch let error as NSError
{
print(error.localizedDescription)
}
}
func post(theData: Data) -> Void
{
self.requester.postRequest("www.url.com", headers: nil, data: theData, callback: {(response: HTTPResponseWithData) -> Void in
if response.statusCode == 200 && response.data != nil && HTTPHeader.isContentTypeJSON(response.mimeType)
{
print(response.data!)
do
{
if let test = try JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions()) as? Dictionary<String, Any>
{
print("test = \(test)")
}
}
catch
{
print("ERROR parsing data")
}
}
else
{
}
});
}
What I get back from the output is:
test = ["imei": <null>]
I've looked at numerous questions and answers on SO regarding this, and besides my implementation being in different classes, I don't see what could possibly be wrong.
Here's some snippet of the PHP code:
header("Content-Type: application/json");
$imei = $_POST["imei"];
$something_else = $_POST["something_else"];
$mysqli = new mysqli($host, $userid, $password, $database);
if ($mysqli->connect_errno)
{
echo json_encode(array("success" => false, "message" => $mysqli->connect_error, "sqlerrno" => $mysqli->connect_errno));
exit();
}
echo json_encode( array('imei'=>$imei) );
What exactly is wrong with my POST request implementation that is not allowing me to submit the IMEI to the database?
If it helps, the RESPONSE output is:
RESPONSE: Optional( { URL:
http://www.url.com } { status code: 200, headers {
Connection = "Keep-Alive";
"Content-Type" = "application/json";
Date = "Mon, 02 Jan 2017 08:07:54 GMT";
"Keep-Alive" = "timeout=2, max=96";
Server = Apache;
"Transfer-Encoding" = Identity; } })
UPDATE: After further testing, I replaced the above php code after the header with the following code, and now the imei is reported:
$handle = fopen("php://input", "rb");
$raw_post_data = '';
while (!feof($handle))
{
$raw_post_data .= fread($handle, 8192);
}
fclose($handle);
$request_data = json_decode($raw_post_data, true);
$imei = $request_data["imei"];
I'm confused, why is it the case that the updated php code works but the one involving $_POST does not?
See the $_POST documentation which says it is:
An associative array of variables passed to the current script via the HTTP POST method when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request.
But you're not doing x-www-form-urlencoded request. You're performing an application/json request. So you can't use $_POST. Use php://input (e.g., as discussed here: iOS Send JSON data in POST request using NSJSONSerialization).
I have to send NSAttributedString to mysql and be able to edit in on my website. I thought that the best idea will be converting NSAttributedString into array of Strings. But I have a problem with sending it. Firstly code(done thanks to one user of stack overflow:)):
func uploadNote(user: String, title: String, category: String, content: [String]) {
let URL: NSURL = NSURL(string: "http://site/uploadNote.php")!
let string = arrayToJSONBase64(content)
print(string)
let request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
request.HTTPMethod = "POST"
let bodyData = "content=\(string)"
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);
print("appended data to body")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data, response, error in
print("Sent request")
}
task.resume()
}
func arrayToJSONBase64(arr: [String]) -> String {
let data = try?NSJSONSerialization.dataWithJSONObject(arr, options: .PrettyPrinted)
let contentJsonBase64 = data!.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
return contentJsonBase64
}
And php:
<?php
// uploadr.php
require_once 'log.php';
class Handler {
use Logger;
public function handleRequest($arg) {
try {
$this->log(__METHOD__);
$this->log(print_r($arg, true));
$json = base64_decode($arg['content']);
$this->log($json);
// just write to a file
file_put_contents('data.json', $json);
}
catch(PDOException $e) {
$this->log('Failed: ' . $e->getMessage());
}
catch( Exception $e) {
}
}
}
$handler = new Handler();
$handler->handleRequest($_POST);
log.php:
<?php
trait Logger {
function log($msg) {
file_put_contents('app.log', strftime('%Y-%m-%d %T ') . $msg . "\n", FILE_APPEND);
}
}
The problem is that when I send an array like ["one", "two", "three"] everything is ok, it's saved in data.json and everything is all right. But when I try to send HTML code my data.json looks like this:
MY OUTPUT