• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

src/H19-Apr-2018-4,7733,479

t/H19-Apr-2018-3,6832,930

util/H19-Apr-2018-236176

.gitattributesH A D19-Apr-201827 21

.gitignoreH A D19-Apr-2018481 5554

.travis.ymlH A D19-Apr-20181.9 KiB6050

README.markdownH A D19-Apr-201826.8 KiB809541

configH A D19-Apr-20181.4 KiB3227

valgrind.suppressH A D19-Apr-20181.7 KiB9493

README.markdown

1Name
2====
3
4**ngx_memc** - An extended version of the standard memcached module that supports set, add, delete, and many more memcached commands.
5
6*This module is not distributed with the Nginx source.* See [the installation instructions](#installation).
7
8Table of Contents
9=================
10
11* [Version](#version)
12* [Synopsis](#synopsis)
13* [Description](#description)
14    * [Keep-alive connections to memcached servers](#keep-alive-connections-to-memcached-servers)
15    * [How it works](#how-it-works)
16* [Memcached commands supported](#memcached-commands-supported)
17    * [get $memc_key](#get-memc_key)
18    * [set $memc_key $memc_flags $memc_exptime $memc_value](#set-memc_key-memc_flags-memc_exptime-memc_value)
19    * [add $memc_key $memc_flags $memc_exptime $memc_value](#add-memc_key-memc_flags-memc_exptime-memc_value)
20    * [replace $memc_key $memc_flags $memc_exptime $memc_value](#replace-memc_key-memc_flags-memc_exptime-memc_value)
21    * [append $memc_key $memc_flags $memc_exptime $memc_value](#append-memc_key-memc_flags-memc_exptime-memc_value)
22    * [prepend $memc_key $memc_flags $memc_exptime $memc_value](#prepend-memc_key-memc_flags-memc_exptime-memc_value)
23    * [delete $memc_key](#delete-memc_key)
24    * [delete $memc_key $memc_exptime](#delete-memc_key-memc_exptime)
25    * [incr $memc_key $memc_value](#incr-memc_key-memc_value)
26    * [decr $memc_key $memc_value](#decr-memc_key-memc_value)
27    * [flush_all](#flush_all)
28    * [flush_all $memc_exptime](#flush_all-memc_exptime)
29    * [stats](#stats)
30    * [version](#version)
31* [Directives](#directives)
32    * [memc_pass](#memc_pass)
33    * [memc_cmds_allowed](#memc_cmds_allowed)
34    * [memc_flags_to_last_modified](#memc_flags_to_last_modified)
35    * [memc_connect_timeout](#memc_connect_timeout)
36    * [memc_send_timeout](#memc_send_timeout)
37    * [memc_read_timeout](#memc_read_timeout)
38    * [memc_buffer_size](#memc_buffer_size)
39    * [memc_ignore_client_abort](#memc_ignore_client_abort)
40* [Installation](#installation)
41    * [For Developers](#for-developers)
42* [Compatibility](#compatibility)
43* [Community](#community)
44    * [English Mailing List](#english-mailing-list)
45    * [Chinese Mailing List](#chinese-mailing-list)
46* [Report Bugs](#report-bugs)
47* [Source Repository](#source-repository)
48* [Changes](#changes)
49* [Test Suite](#test-suite)
50* [TODO](#todo)
51* [Getting involved](#getting-involved)
52* [Author](#author)
53* [Copyright & License](#copyright--license)
54* [See Also](#see-also)
55
56Version
57=======
58
59This document describes ngx_memc [v0.19](http://github.com/openresty/memc-nginx-module/tags) released on 19 April 2018.
60
61Synopsis
62========
63
64```nginx
65
66 # GET /foo?key=dog
67 #
68 # POST /foo?key=cat
69 # Cat's value...
70 #
71 # PUT /foo?key=bird
72 # Bird's value...
73 #
74 # DELETE /foo?key=Tiger
75 location /foo {
76     set $memc_key $arg_key;
77
78     # $memc_cmd defaults to get for GET,
79     #   add for POST, set for PUT, and
80     #   delete for the DELETE request method.
81
82     memc_pass 127.0.0.1:11211;
83 }
84```
85
86```nginx
87
88 # GET /bar?cmd=get&key=cat
89 #
90 # POST /bar?cmd=set&key=dog
91 # My value for the "dog" key...
92 #
93 # DELETE /bar?cmd=delete&key=dog
94 # GET /bar?cmd=delete&key=dog
95 location /bar {
96     set $memc_cmd $arg_cmd;
97     set $memc_key $arg_key;
98     set $memc_flags $arg_flags; # defaults to 0
99     set $memc_exptime $arg_exptime; # defaults to 0
100
101     memc_pass 127.0.0.1:11211;
102 }
103```
104
105```nginx
106
107 # GET /bar?cmd=get&key=cat
108 # GET /bar?cmd=set&key=dog&val=animal&flags=1234&exptime=2
109 # GET /bar?cmd=delete&key=dog
110 # GET /bar?cmd=flush_all
111 location /bar {
112     set $memc_cmd $arg_cmd;
113     set $memc_key $arg_key;
114     set $memc_value $arg_val;
115     set $memc_flags $arg_flags; # defaults to 0
116     set $memc_exptime $arg_exptime; # defaults to 0
117
118     memc_cmds_allowed get set add delete flush_all;
119
120     memc_pass 127.0.0.1:11211;
121 }
122```
123
124```nginx
125
126   http {
127     ...
128     upstream backend {
129        server 127.0.0.1:11984;
130        server 127.0.0.1:11985;
131     }
132     server {
133         location /stats {
134             set $memc_cmd stats;
135             memc_pass backend;
136         }
137         ...
138     }
139   }
140   ...
141```
142
143```nginx
144
145 # read the memcached flags into the Last-Modified header
146 # to respond 304 to conditional GET
147 location /memc {
148     set $memc_key $arg_key;
149
150     memc_pass 127.0.0.1:11984;
151
152     memc_flags_to_last_modified on;
153 }
154```
155
156```nginx
157
158 location /memc {
159     set $memc_key foo;
160     set $memc_cmd get;
161
162     # access the unix domain socket listend by memcached
163     memc_pass unix:/tmp/memcached.sock;
164 }
165```
166
167Description
168===========
169
170This module extends the standard [memcached module](http://nginx.org/en/docs/http/ngx_http_memcached_module.html) to support almost the whole [memcached ascii protocol](http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt).
171
172It allows you to define a custom [REST](http://en.wikipedia.org/wiki/REST) interface to your memcached servers or access memcached in a very efficient way from within the nginx server by means of subrequests or [independent fake requests](http://github.com/srlindsay/nginx-independent-subrequest).
173
174This module is not supposed to be merged into the Nginx core because I've used [Ragel](http://www.complang.org/ragel/) to generate the memcached response parsers (in C) for joy :)
175
176If you are going to use this module to cache location responses out of the box, try [srcache-nginx-module](http://github.com/openresty/srcache-nginx-module) with this module to achieve that.
177
178When used in conjunction with [lua-nginx-module](http://github.com/openresty/lua-nginx-module), it is recommended to use the [lua-resty-memcached](http://github.com/openresty/lua-resty-memcached) library instead of this module though, because the former is much more flexible and memory-efficient.
179
180[Back to TOC](#table-of-contents)
181
182Keep-alive connections to memcached servers
183-------------------------------------------
184
185You need [HttpUpstreamKeepaliveModule](http://wiki.nginx.org/HttpUpstreamKeepaliveModule) together with this module for keep-alive TCP connections to your backend memcached servers.
186
187Here's a sample configuration:
188
189```nginx
190
191   http {
192     upstream backend {
193       server 127.0.0.1:11211;
194
195       # a pool with at most 1024 connections
196       # and do not distinguish the servers:
197       keepalive 1024;
198     }
199
200     server {
201         ...
202         location /memc {
203             set $memc_cmd get;
204             set $memc_key $arg_key;
205             memc_pass backend;
206         }
207     }
208   }
209```
210
211[Back to TOC](#table-of-contents)
212
213How it works
214------------
215
216It implements the memcached TCP protocol all by itself, based upon the `upstream` mechanism. Everything involving I/O is non-blocking.
217
218The module itself does not keep TCP connections to the upstream memcached servers across requests, just like other upstream modules. For a working solution, see section [Keep-alive connections to memcached servers](#keep-alive-connections-to-memcached-servers).
219
220[Back to TOC](#table-of-contents)
221
222Memcached commands supported
223============================
224
225The memcached storage commands [set](#set-memc_key-memc_flags-memc_exptime-memc_value), [add](#add-memc_key-memc_flags-memc_exptime-memc_value), [replace](#replace-memc_key-memc_flags-memc_exptime-memc_value), [prepend](#prepend-memc_key-memc_flags-memc_exptime-memc_value), and [append](#append-memc_key-memc_flags-memc_exptime-memc_value) uses the `$memc_key` as the key, `$memc_exptime` as the expiration time (or delay) (defaults to 0), `$memc_flags` as the flags (defaults to 0), to build the corresponding memcached queries.
226
227If `$memc_value` is not defined at all, then the request body will be used as the value of the `$memc_value` except for the [incr](#incr-memc_key-memc_value) and [decr](#decr-memc_key-memc_value) commands. Note that if `$memc_value` is defined as an empty string (`""`), that empty string will still be used as the value as is.
228
229The following memcached commands have been implemented and tested (with their parameters marked by corresponding
230nginx variables defined by this module):
231
232[Back to TOC](#table-of-contents)
233
234get $memc_key
235-------------
236
237Retrieves the value using a key.
238
239```nginx
240
241   location /foo {
242       set $memc_cmd 'get';
243       set $memc_key 'my_key';
244
245       memc_pass 127.0.0.1:11211;
246
247       add_header X-Memc-Flags $memc_flags;
248   }
249```
250
251Returns `200 OK` with the value put into the response body if the key is found, or `404 Not Found` otherwise. The `flags` number will be set into the `$memc_flags` variable so it's often desired to put that info into the response headers by means of the standard [add_header directive](http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header).
252
253It returns `502` for `ERROR`, `CLIENT_ERROR`, or `SERVER_ERROR`.
254
255[Back to TOC](#table-of-contents)
256
257set $memc_key $memc_flags $memc_exptime $memc_value
258---------------------------------------------------
259
260To use the request body as the memcached value, just avoid setting the `$memc_value` variable:
261
262```nginx
263
264   # POST /foo
265   # my value...
266   location /foo {
267       set $memc_cmd 'set';
268       set $memc_key 'my_key';
269       set $memc_flags 12345;
270       set $memc_exptime 24;
271
272       memc_pass 127.0.0.1:11211;
273   }
274```
275
276Or let the `$memc_value` hold the value:
277
278```nginx
279
280   location /foo {
281       set $memc_cmd 'set';
282       set $memc_key 'my_key';
283       set $memc_flags 12345;
284       set $memc_exptime 24;
285       set $memc_value 'my_value';
286
287       memc_pass 127.0.0.1:11211;
288   }
289```
290
291Returns `201 Created` if the upstream memcached server replies `STORED`, `200` for `NOT_STORED`, `404` for `NOT_FOUND`, `502` for `ERROR`, `CLIENT_ERROR`, or `SERVER_ERROR`.
292
293The original memcached responses are returned as the response body except for `404 NOT FOUND`.
294
295[Back to TOC](#table-of-contents)
296
297add $memc_key $memc_flags $memc_exptime $memc_value
298---------------------------------------------------
299
300Similar to the [set command](#set-memc_key-memc_flags-memc_exptime-memc_value).
301
302[Back to TOC](#table-of-contents)
303
304replace $memc_key $memc_flags $memc_exptime $memc_value
305-------------------------------------------------------
306
307Similar to the [set command](#set-memc_key-memc_flags-memc_exptime-memc_value).
308
309[Back to TOC](#table-of-contents)
310
311append $memc_key $memc_flags $memc_exptime $memc_value
312------------------------------------------------------
313
314Similar to the [set command](#set-memc_key-memc_flags-memc_exptime-memc_value).
315
316Note that at least memcached version 1.2.2 does not support the "append" and "prepend" commands. At least 1.2.4 and later versions seem to supports these two commands.
317
318[Back to TOC](#table-of-contents)
319
320prepend $memc_key $memc_flags $memc_exptime $memc_value
321-------------------------------------------------------
322
323Similar to the [append command](#append-memc_key-memc_flags-memc_exptime-memc_value).
324
325[Back to TOC](#table-of-contents)
326
327delete $memc_key
328----------------
329
330Deletes the memcached entry using a key.
331
332```nginx
333
334   location /foo
335       set $memc_cmd delete;
336       set $memc_key my_key;
337
338       memc_pass 127.0.0.1:11211;
339   }
340```
341
342Returns `200 OK` if deleted successfully, `404 Not Found` for `NOT_FOUND`, or `502` for `ERROR`, `CLIENT_ERROR`, or `SERVER_ERROR`.
343
344The original memcached responses are returned as the response body except for `404 NOT FOUND`.
345
346[Back to TOC](#table-of-contents)
347
348delete $memc_key $memc_exptime
349------------------------------
350
351Similar to the [delete $memc_key](#delete-memc_key) command except it accepts an optional `expiration` time specified by the `$memc_exptime` variable.
352
353This command is no longer available in the latest memcached version 1.4.4.
354
355[Back to TOC](#table-of-contents)
356
357incr $memc_key $memc_value
358--------------------------
359
360Increments the existing value of `$memc_key` by the amount specified by `$memc_value`:
361
362```nginx
363
364   location /foo {
365       set $memc_cmd incr;
366       set $memc_key my_key;
367       set $memc_value 2;
368       memc_pass 127.0.0.1:11211;
369   }
370```
371
372In the preceding example, every time we access `/foo` will cause the value of `my_key` increments by `2`.
373
374Returns `200 OK` with the new value associated with that key as the response body if successful, or `404 Not Found` if the key is not found.
375
376It returns `502` for `ERROR`, `CLIENT_ERROR`, or `SERVER_ERROR`.
377
378[Back to TOC](#table-of-contents)
379
380decr $memc_key $memc_value
381--------------------------
382
383Similar to [incr $memc_key $memc_value](#incr-memc_key-memc_value).
384
385[Back to TOC](#table-of-contents)
386
387flush_all
388---------
389
390Mark all the keys on the memcached server as expired:
391
392```nginx
393
394   location /foo {
395       set $memc_cmd flush_all;
396       memc_pass 127.0.0.1:11211;
397   }
398```
399
400[Back to TOC](#table-of-contents)
401
402flush_all $memc_exptime
403-----------------------
404
405Just like [flush_all](#flush_all) but also accepts an expiration time specified by the `$memc_exptime` variable.
406
407[Back to TOC](#table-of-contents)
408
409stats
410-----
411
412Causes the memcached server to output general-purpose statistics and settings
413
414```nginx
415
416   location /foo {
417       set $memc_cmd stats;
418       memc_pass 127.0.0.1:11211;
419   }
420```
421
422Returns `200 OK` if the request succeeds, or 502 for `ERROR`, `CLIENT_ERROR`, or `SERVER_ERROR`.
423
424The raw `stats` command output from the upstream memcached server will be put into the response body.
425
426[Back to TOC](#table-of-contents)
427
428version
429-------
430
431Queries the memcached server's version number:
432
433```nginx
434
435   location /foo {
436       set $memc_cmd version;
437       memc_pass 127.0.0.1:11211;
438   }
439```
440
441Returns `200 OK` if the request succeeds, or 502 for `ERROR`, `CLIENT_ERROR`, or `SERVER_ERROR`.
442
443The raw `version` command output from the upstream memcached server will be put into the response body.
444
445[Back to TOC](#table-of-contents)
446
447Directives
448==========
449
450All the standard [memcached module](http://nginx.org/en/docs/http/ngx_http_memcached_module.html) directives in nginx 0.8.28 are directly inherited, with the `memcached_` prefixes replaced by `memc_`. For example, the `memcached_pass` directive is spelled `memc_pass`.
451
452Here we only document the most important two directives (the latter is a new directive introduced by this module).
453
454[Back to TOC](#table-of-contents)
455
456memc_pass
457---------
458
459**syntax:** *memc_pass <memcached server IP address>:<memcached server port>*
460
461**syntax:** *memc_pass <memcached server hostname>:<memcached server port>*
462
463**syntax:** *memc_pass <upstream_backend_name>*
464
465**syntax:** *memc_pass unix:<path_to_unix_domain_socket>*
466
467**default:** *none*
468
469**context:** *http, server, location, if*
470
471**phase:** *content*
472
473Specify the memcached server backend.
474
475[Back to TOC](#table-of-contents)
476
477memc_cmds_allowed
478-----------------
479**syntax:** *memc_cmds_allowed <cmd>...*
480
481**default:** *none*
482
483**context:** *http, server, location, if*
484
485Lists memcached commands that are allowed to access. By default, all the memcached commands supported by this module are accessible.
486An example is
487
488```nginx
489
490    location /foo {
491        set $memc_cmd $arg_cmd;
492        set $memc_key $arg_key;
493        set $memc_value $arg_val;
494
495        memc_pass 127.0.0.1:11211;
496
497        memc_cmds_allowed get;
498    }
499```
500
501[Back to TOC](#table-of-contents)
502
503memc_flags_to_last_modified
504---------------------------
505**syntax:** *memc_flags_to_last_modified on|off*
506
507**default:** *off*
508
509**context:** *http, server, location, if*
510
511Read the memcached flags as epoch seconds and set it as the value of the `Last-Modified` header. For conditional GET, it will signal nginx to return `304 Not Modified` response to save bandwidth.
512
513[Back to TOC](#table-of-contents)
514
515memc_connect_timeout
516--------------------
517**syntax:** *memc_connect_timeout <time>*
518
519**default:** *60s*
520
521**context:** *http, server, location*
522
523The timeout for connecting to the memcached server, in seconds by default.
524
525It's wise to always explicitly specify the time unit to avoid confusion. Time units supported are "s"(seconds), "ms"(milliseconds), "y"(years), "M"(months), "w"(weeks), "d"(days), "h"(hours), and "m"(minutes).
526
527This time must be less than 597 hours.
528
529[Back to TOC](#table-of-contents)
530
531memc_send_timeout
532-----------------
533**syntax:** *memc_send_timeout <time>*
534
535**default:** *60s*
536
537**context:** *http, server, location*
538
539The timeout for sending TCP requests to the memcached server, in seconds by default.
540
541It is wise to always explicitly specify the time unit to avoid confusion. Time units supported are "s"(seconds), "ms"(milliseconds), "y"(years), "M"(months), "w"(weeks), "d"(days), "h"(hours), and "m"(minutes).
542
543This time must be less than 597 hours.
544
545[Back to TOC](#table-of-contents)
546
547memc_read_timeout
548-----------------
549**syntax:** *memc_read_timeout <time>*
550
551**default:** *60s*
552
553**context:** *http, server, location*
554
555The timeout for reading TCP responses from the memcached server, in seconds by default.
556
557It's wise to always explicitly specify the time unit to avoid confusion. Time units supported are "s"(seconds), "ms"(milliseconds), "y"(years), "M"(months), "w"(weeks), "d"(days), "h"(hours), and "m"(minutes).
558
559This time must be less than 597 hours.
560
561[Back to TOC](#table-of-contents)
562
563memc_buffer_size
564----------------
565**syntax:** *memc_buffer_size <size>*
566
567**default:** *4k/8k*
568
569**context:** *http, server, location*
570
571This buffer size is used for the memory buffer to hold
572
573* the complete response for memcached commands other than `get`,
574* the complete response header (i.e., the first line of the response) for the `get` memcached command.
575
576This default size is the page size, may be `4k` or `8k`.
577
578[Back to TOC](#table-of-contents)
579
580memc_ignore_client_abort
581------------------------
582**syntax:** *memc_ignore_client_abort on|off*
583
584**default:** *off*
585
586**context:** *location*
587
588Determines whether the connection with a memcache server should be closed when a client closes a connection without waiting for a response.
589
590This directive was first added in the `v0.14` release.
591
592[Back to TOC](#table-of-contents)
593
594Installation
595============
596
597You're recommended to install this module (as well as the Nginx core and many other goodies) via the [OpenResty bundle](http://openresty.org). See the [installation steps](http://openresty.org/#Installation) for `OpenResty`.
598
599Alternatively, you can compile this module into the standard Nginx source distribution by hand:
600
601Grab the nginx source code from [nginx.org](http://nginx.org/), for example,
602the version 1.13.6 (see [nginx compatibility](#compatibility)), and then build the source with this module:
603
604```bash
605
606 wget 'http://nginx.org/download/nginx-1.13.6.tar.gz'
607 tar -xzvf nginx-1.13.6.tar.gz
608 cd nginx-1.13.6/
609
610 # Here we assume you would install you nginx under /opt/nginx/.
611 ./configure --prefix=/opt/nginx \
612     --add-module=/path/to/memc-nginx-module
613
614 make -j2
615 make install
616```
617
618Download the latest version of the release tarball of this module from [memc-nginx-module file list](http://github.com/openresty/memc-nginx-module/tags).
619
620Starting from NGINX 1.9.11, you can also compile this module as a dynamic module, by using the `--add-dynamic-module=PATH` option instead of `--add-module=PATH` on the
621`./configure` command line above. And then you can explicitly load the module in your `nginx.conf` via the [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module)
622directive, for example,
623
624```nginx
625load_module /path/to/modules/ngx_http_memc_module.so;
626```
627
628[Back to TOC](#table-of-contents)
629
630For Developers
631--------------
632
633The memached response parsers were generated by [Ragel](http://www.complang.org/ragel/). If you want to
634regenerate the parser's C file, i.e., [src/ngx_http_memc_response.c](http://github.com/openresty/memc-nginx-module/blob/master/src/ngx_http_memc_response.c), use the following command from the root of the memc module's source tree:
635
636```bash
637
638 $ ragel -G2 src/ngx_http_memc_response.rl
639```
640
641[Back to TOC](#table-of-contents)
642
643Compatibility
644=============
645
646The following versions of Nginx should work with this module:
647
648* **1.13.x**                      (last tested: 1.13.6)
649* **1.12.x**
650* **1.11.x**                      (last tested: 1.11.2)
651* **1.10.x**
652* **1.9.x**                       (last tested: 1.9.15)
653* **1.8.x**
654* **1.7.x**                       (last tested: 1.7.10)
655* **1.6.x**
656* **1.5.x**                       (last tested: 1.5.12)
657* **1.4.x**                       (last tested: 1.4.4)
658* **1.2.x**                       (last tested: 1.2.9)
659* **1.1.x**                       (last tested: 1.1.5)
660* **1.0.x**                       (last tested: 1.0.10)
661* **0.9.x**                       (last tested: 0.9.4)
662* **0.8.x**                       (last tested: 0.8.54)
663* **0.7.x >= 0.7.46**             (last tested: 0.7.68)
664
665It's worth mentioning that some 0.7.x versions older than 0.7.46 might also work, but I can't easily test them because the test suite makes extensive use of the [echo module](http://github.com/openresty/echo-nginx-module)'s [echo_location directive](http://github.com/openresty/echo-nginx-module#echo_location), which requires at least nginx 0.7.46 :)
666
667Earlier versions of Nginx like 0.6.x and 0.5.x will *not* work.
668
669If you find that any particular version of Nginx above 0.7.46 does not work with this module, please consider [reporting a bug](#report-bugs).
670
671[Back to TOC](#table-of-contents)
672
673Community
674=========
675
676[Back to TOC](#table-of-contents)
677
678English Mailing List
679--------------------
680
681The [openresty-en](https://groups.google.com/group/openresty-en) mailing list is for English speakers.
682
683[Back to TOC](#table-of-contents)
684
685Chinese Mailing List
686--------------------
687
688The [openresty](https://groups.google.com/group/openresty) mailing list is for Chinese speakers.
689
690[Back to TOC](#table-of-contents)
691
692Report Bugs
693===========
694
695Although a lot of effort has been put into testing and code tuning, there must be some serious bugs lurking somewhere in this module. So whenever you are bitten by any quirks, please don't hesitate to
696
6971. create a ticket on the [issue tracking interface](http://github.com/openresty/memc-nginx-module/issues) provided by GitHub,
6981. or send a bug report or even patches to the [nginx mailing list](http://mailman.nginx.org/mailman/listinfo/nginx).
699
700[Back to TOC](#table-of-contents)
701
702Source Repository
703=================
704
705Available on github at [openresty/memc-nginx-module](http://github.com/openresty/memc-nginx-module).
706
707[Back to TOC](#table-of-contents)
708
709Changes
710=======
711
712The changes of every release of this module can be obtained from the OpenResty bundle's change logs:
713
714<http://openresty.org/#Changes>
715
716[Back to TOC](#table-of-contents)
717
718Test Suite
719==========
720
721This module comes with a Perl-driven test suite. The [test cases](http://github.com/openresty/memc-nginx-module/tree/master/t/) are
722[declarative](http://github.com/openresty/memc-nginx-module/blob/master/t/storage.t) too. Thanks to the [Test::Base](http://search.cpan.org/perldoc?Test::Base) module in the Perl world.
723
724To run it on your side:
725
726```bash
727
728 $ PATH=/path/to/your/nginx-with-memc-module:$PATH prove -r t
729```
730
731You need to terminate any Nginx processes before running the test suite if you have changed the Nginx server binary.
732
733Either [LWP::UserAgent](http://search.cpan.org/perldoc?LWP::UserAgent) or [IO::Socket](http://search.cpan.org/perldoc?IO::Socket) is used by the [test scaffold](http://github.com/openresty/memc-nginx-module/blob/master/test/lib/Test/Nginx/LWP.pm).
734
735Because a single nginx server (by default, `localhost:1984`) is used across all the test scripts (`.t` files), it's meaningless to run the test suite in parallel by specifying `-jN` when invoking the `prove` utility.
736
737You should also keep a memcached server listening on the `11211` port at localhost before running the test suite.
738
739Some parts of the test suite requires modules [rewrite](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html) and [echo](http://github.com/openresty/echo-nginx-module) to be enabled as well when building Nginx.
740
741[Back to TOC](#table-of-contents)
742
743TODO
744====
745
746* add support for the memcached commands `cas`, `gets` and `stats $memc_value`.
747* add support for the `noreply` option.
748
749[Back to TOC](#table-of-contents)
750
751Getting involved
752================
753
754You'll be very welcomed to submit patches to the [author](#author) or just ask for a commit bit to the [source repository](#source-repository) on GitHub.
755
756[Back to TOC](#table-of-contents)
757
758Author
759======
760
761Yichun "agentzh" Zhang (章亦春) *&lt;agentzh@gmail.com&gt;*, OpenResty Inc.
762
763This wiki page is also maintained by the author himself, and everybody is encouraged to improve this page as well.
764
765[Back to TOC](#table-of-contents)
766
767Copyright & License
768===================
769
770The code base is borrowed directly from the standard [memcached module](http://nginx.org/en/docs/http/ngx_http_memcached_module.html) in the Nginx core. This part of code is copyrighted by Igor Sysoev and Nginx Inc.
771
772Copyright (c) 2009-2018, Yichun "agentzh" Zhang (章亦春) <agentzh@gmail.com>, OpenResty Inc.
773
774This module is licensed under the terms of the BSD license.
775
776Redistribution and use in source and binary forms, with or without
777modification, are permitted provided that the following conditions
778are met:
779
780* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
781* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
782
783THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
784"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
785LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
786A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
787HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
788SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
789TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
790PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
791LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
792NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
793SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
794
795[Back to TOC](#table-of-contents)
796
797See Also
798========
799
800* The original announcement email on the nginx mailing list: [ngx_memc: "an extended version of ngx_memcached that supports set, add, delete, and many more commands"](http://forum.nginx.org/read.php?2,28359)
801* My slides demonstrating various ngx_memc usage: <http://agentzh.org/misc/slides/nginx-conf-scripting/nginx-conf-scripting.html#34> (use the arrow or pageup/pagedown keys on the keyboard to swith pages)
802* The latest [memcached TCP protocol](http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt).
803* The [ngx_srcache](http://github.com/openresty/srcache-nginx-module) module
804* The [lua-resty-memcached](https://github.com/openresty/lua-resty-memcached) library based on the [lua-nginx-module](http://github.com/openresty/lua-nginx-module) cosocket API.
805* The standard [memcached](http://nginx.org/en/docs/http/ngx_http_memcached_module.html) module.
806* The [echo module](http://github.com/openresty/echo-nginx-module) for Nginx module's automated testing.
807* The standard [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module and the 3rd-parth [headers-more](http://github.com/openresty/headers-more-nginx-module) module.
808
809