2

I am using grunt connect server with all those livereload plugins. Developing process was very fast till I added some rest calls. I decided to make some example JSON files which ll be rest calls answers.

So I need to redirect every rest call to some static folder(important I ll put it in target folder) so it ll be outside the Angular folder.

So I need some plugin which transfer calls like:

http.get(localhost:port/x/y/name) to target/jsons_examples/x/y/name.json
http.get(localhost:port/z/name) to target/jsons_examples/z/name.json

grunt file:(1 aplication server, 1 mocking webservices)

grunt.initConfig({
  connect: {
  all: {
    options: {
        port: 10100,
        hostname: "0.0.0.0",
        livereload: true
    }
  },
  webservices_mock: {
    options: {
        port: 8081,
        hostname: "0.0.0.0",
        middleware: function(connect, options, middlewares) {
            middlewares.unshift(function(req, res, next) {
                var pattern = new RegExp('\/rest\/[a-zA-Z0-9\/.]+', 'i'),
                    matches = req.url.match(pattern);

                if (!matches) {
                    return next();
                }

                req.setEncoding('utf8');
                res.writeHead(200, {"Content-Type": "application/json"});
                res.write(grunt.file.read(req.url.replace("/rest", "json_contracts") + "/example.json"));

                res.end();
            });

            return middlewares;
        }
    }
  }
},
...

And now i need in web services mock configuration change the path from json_contracts to path outside angular folder smth like: ././././target/json_contracts

user2771738
  • 913
  • 11
  • 31

1 Answers1

1

You can use middleware option to inject your own URL parser. See the comments to understand how it works:

grunt.initConfig({
  connect: {
    all: {
      options:{
        port: 8080,
        base: dir_to_angular_main_folder
        hostname: "localhost",
        middleware: function(connect, options, middlewares) {
          middlewares.unshift(function(req, res, next) {
            // pattern is a RegExp which is going to find the redirected url
            var pattern = new RegExp('^/x/y/([0-9A-Z]+)$', 'i'),
                // matches is a result which is
                //  - undefined when no match found
                //  - an array with two values when found:
                //    0: the full string
                //    1: the string inside of the brackets (the file name)
                matches = req.url.match(pattern);

            // if your url does not match skip the bottom part
            if (!matches) return next();

            // this runs only if match is found, set up the redirect header
            // up to you to decide whether it is 301 or 302
            // I would keep it 302 for dev purposes (browsers won't cache it)
            res.writeHead(302, {
              Location: '/target/jsons_examples/x/y/' + matches[1] + '.json'
            });

            // send the response
            res.end();
          });

          return middlewares;
        }
      }
    }
  }
});

I guess you will still need to change the pattern to the one you need (x / y / target don't sound as real names).

One can say you can do it easier without matching like this ([0-9A-Z]+) and using the matches here '/target/jsons_examples/x/y/' + matches[1] + '.json' and he will be right. It was made with a name only because it is more flexible, e.g. when you have a folder in between x and y etc. Anyway, as it was said before, you can also make it simpler and just use the following:

res.writeHead(302, {
  Location: '/target/jsons_examples' + req.url + '.json'
});

I could not test it, maybe it gives you some errors, but still I hope this is good enough to give an idea what and how to do.

EDIT

Well, according to the fact that your JSON files are not visible from the webserver side (the root folder is out of scope) you can do some kind of url rewriting instead of redirect:

var fs = require('fs');

grunt.initConfig({
  connect: {
    all: {
      options:{
        port: 8080,
        base: dir_to_angular_main_folder
        hostname: "localhost",
        middleware: function(connect, options, middlewares) {
          middlewares.unshift(function(req, res, next) {
            // pattern is a RegExp which is going to find the redirected url
            var pattern = new RegExp('^/x/y/([0-9A-Z]+)$', 'i'),
                // matches is a result which is
                //  - undefined when no match found
                //  - an array with two values when found:
                //    0: the full string
                //    1: the string inside of the brackets (the file name)
                matches = req.url.match(pattern);

            // if your url does not match skip the bottom part
            if (!matches) return next();

            // this runs only if match is found, set up the redirect header
            // reads the file content and sends as a response
            res.end(fs.readFileSync('/<some-absolute-path>/target/jsons_examples/x/y/' + matches[1] + '.json', 'utf8'));
          });

          return middlewares;
        }
      }
    }
  }
});

Note that you need to include the Nodejs standard fs module on the top of your Gruntfile to make it work. This is again just a prototype, change the paths according to your requirements. Maybe you would also need to write the mime-type as a header of your response, there are already many answers on how to do it in Node as well.

smnbbrv
  • 23,502
  • 9
  • 78
  • 109
  • looks promising, but it not firing for http inside some js controllers. I added simple log console.log('req: ' + req.url) it shows call of my controller as 'app/testController.js' but inside I am using $http.get( or ) and middleware isn't firing for any of file or rest call – user2771738 Oct 05 '15 at 07:35
  • edit: $http.get(examples/user.json) for file it is firing but with prefix 'app/' but for rest noting firing. – user2771738 Oct 05 '15 at 07:44
  • could you for the sake of pure testing try with any of your files just calling in the browser _http://localhost:port/x/y/name_ and tell the result? This will exclude a probability of problems on Angular side, maybe it is not calling something or you have a `` tag... – smnbbrv Oct 05 '15 at 08:36
  • x is webservice class path @Path("/x"). y is webservice method path @Path("/y"). So the rest gonna be localhost:port/x/y. So in jsons project there is folder x/y/example.json. This project is unpacked to my angular project to target folder(not the src!). So calling localhost:port/x/y/name is reference to nothing. localhost:port/x/y is rest call, but I want to develop without rest calls. So I want to redirect all rest calls localhost:port/x/y to file in path /mydir/angularproject/target/x/y/example.json – user2771738 Oct 05 '15 at 09:01
  • I understand that, but still it also should be testable outside of Angular as simple as just calling the URL manually. What I mean if you call this URL it should also redirect you to the corresponding JSON. Does it happen? – smnbbrv Oct 05 '15 at 10:01
  • No, problem is that I dont know how to write properly Location for target folder. When I type localhost:port/x/y/name it redirect me to localhost:port/target/x/y/example.json so it not giving nothing, we are still in angular folder. Instead of this redirection it should just return for me json from path /media/data/project/target/x/y/example.json – user2771738 Oct 05 '15 at 10:24
  • I ve added code in first post, which is close to solution, just dont know how to write location for target folder – user2771738 Oct 05 '15 at 10:38
  • ok, maybe now u ll help me I just replace path from rest to path to file. Problem is that webservices are on other machines/ports so this middleware isn't firing. Code in first post. – user2771738 Oct 05 '15 at 11:37
  • ok, I ve made it. I mocked the webservices server. So now only problem is that I replace rest call to file from angular folder while I need file from outside angular folder. So question is how to get file from any location. – user2771738 Oct 05 '15 at 11:54
  • @user2771738 added another version, see EDIT section – smnbbrv Oct 07 '15 at 08:13
  • Ye, that's something what i looked for :) Anyway I get suggestion to use serve-static plugin. And serve some static folder instead those weird replace statement. Your solution is good, but the most elegance would be serve-static which I cannot implement (some syntax errors whole time). – user2771738 Oct 07 '15 at 12:32