0

I have a web application with front end based on angular and back end as a spring rest API. I'm using grunt connect to serve the front end while the rest api runs on localhst:8080, the grunt server runs on localhost:9002. So from angular, when I'm sending an http call to the back end server using angular-resource, I'm getting following error :

Failed to load localhost:8080/api/v1/user: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https

angular.js:14800 Possibly unhandled rejection: {"data":null,"status":-1,"config":{"method":"POST","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"localhost:8080/api/v1/user","data":{"user":{"email":"a","password":"a"}},"headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json;charset=utf-8"}},"statusText":"","xhrStatus":"error","resource":{"user":"..."}}

JS File :

angular.module('userModule').factory('userService',function($resource){
  var dataResource = $resource('user',{},
    {

      saveUser :{
        method: 'POST',
        url:'localhost:8080/api/v1/user',
        params : '@user'  
      },

    });
    return dataResource;

});

Gruntfile

'use strict';

module.exports = function (grunt) {
  var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest;

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  var serveStatic = require('serve-static');

  // Define the configuration for all the tasks
  grunt.initConfig({

    pkg: grunt.file.readJSON('package.json'),

    clean: ["dist"],

    htmlmin: {                                     // Task
      dist: {                                      // Target
        options: {                                 // Target options
          removeComments: true,
          collapseWhitespace: true
        },
        files: {                                   // Dictionary of files
          'dist/index.html': 'dist/index.html'     // 'destination': 'source'
        }
      }
    },

    copy: {
      main: {
        expand: true,
        cwd: '.',
        src: ['**', /* '!js/**', '!lib/**', */ '!**/*.css', '!node_modules/**', '!Gruntfile.js', '!package.json', '!package-lock.json'],
        dest: 'dist/'
      },
      fonts: {
        expand: true,
        cwd: 'lib/fonts',
        src: ['**'],
        dest: 'dist/fonts'
      }
    },

    rev: {
      files: {
        src: ['dist/**/*.{js,css}', '!dist/lib/**/*.{js,css}', '!dist/js/services/**/*.{js,css}']
      }
    },

    useminPrepare: {
      html: 'index.html'
    },

    usemin: {
      html: ['dist/index.html']
    },

    uglify: {
      options: {
        report: 'min',
        mangle: false
      }
    },

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      js: {
        files: ['js/*.js'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      styles: {
        files: ['css/*.css']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '*.html',
          'css/*.css',
          'images/*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9002,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: '0.0.0.0',
        livereload: 35730,
        base: '.',
        middleware: function (connect, options, middlewares) {
            middlewares.unshift(function (req, res, next) {
                res.setHeader('Access-Control-Allow-Origin', '*');
                res.setHeader('Access-Control-Allow-Methods', '*');
                return next();

            });

            return middlewares;
        }

      },

      proxies: [
        {
          context: '/api/v1',
          host: 'localhost',
          port: 8080,
          changeOrigin: true
        }
      ],
      livereload: {
        options: {
          open: false,
          middleware: function (connect) {
            return [
              proxySnippet,
              serveStatic('.')
            ];
          }
        }
      }
    },
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    grunt.task.run([
      'configureProxies',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('default', [
    'clean', 'copy', 'useminPrepare', 'concat', 'uglify', 'cssmin', 'rev', 'usemin', 'htmlmin'
  ]);

};

Can some one tell me is it possible to send http calls with grunt connect?

Paras
  • 3,191
  • 6
  • 41
  • 77

1 Answers1

0

You are running into CORS issue, This happens when you are making request to a different domain or schema http https or different port (your case falls in this). There are two options.

  1. Allow CORS on your backend server (spring backed server in your case).

    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
            // by default uses a Bean by the name of corsConfigurationSource
            .cors().and()
            ...
        }
    
        @Bean
        CorsConfigurationSource corsConfigurationSource() {
            CorsConfiguration configuration = new CorsConfiguration();
            configuration.setAllowedOrigins(Arrays.asList("http://localhost:8080"));
            configuration.setAllowedMethods(Arrays.asList("GET","POST"));
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", configuration);
            return source;
        }
    }
    

    Further information can be found here.

  2. Configure Front end and backend in same full fledged HTTP server like apache, nginx and setup the request handling as below.

    a. Serve all static/angular resources on default path. (localhost/)
    b. Send all your backend request to localhost/api/ and proxy it to your backend localhost:8080/api application.

    Nginx example:

    server {
        listen 80;
    
        # The host name to respond to
        server_name localhost;
    
        location /api/ {
            # Backend nodejs server
            proxy_pass          http://localhost:8080/api;
            proxy_http_version  1.1;
            proxy_set_header    Upgrade     $http_upgrade;
            proxy_set_header    Connection  $connection_upgrade;
        }
    
        location / {
            root /angular directory path/; 
        }
    }
    
RobC
  • 22,977
  • 20
  • 73
  • 80
sanjay patel
  • 449
  • 8
  • 17