Mercurial > hg > nginx
comparison src/http/modules/ngx_http_proxy_module.c @ 4925:32030fa8cb14
Request body: chunked parsing moved to ngx_http_parse.c from proxy.
No functional changes.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 21 Nov 2012 00:59:16 +0000 |
parents | 8036fc6af2df |
children | 93294110728f |
comparison
equal
deleted
inserted
replaced
4924:caca5603bded | 4925:32030fa8cb14 |
---|---|
79 } ngx_http_proxy_loc_conf_t; | 79 } ngx_http_proxy_loc_conf_t; |
80 | 80 |
81 | 81 |
82 typedef struct { | 82 typedef struct { |
83 ngx_http_status_t status; | 83 ngx_http_status_t status; |
84 ngx_http_chunked_t chunked; | |
84 ngx_http_proxy_vars_t vars; | 85 ngx_http_proxy_vars_t vars; |
85 size_t internal_body_length; | 86 size_t internal_body_length; |
86 | |
87 ngx_uint_t state; | |
88 off_t size; | |
89 off_t length; | |
90 | 87 |
91 ngx_uint_t head; /* unsigned head:1 */ | 88 ngx_uint_t head; /* unsigned head:1 */ |
92 } ngx_http_proxy_ctx_t; | 89 } ngx_http_proxy_ctx_t; |
93 | 90 |
94 | 91 |
1250 | 1247 |
1251 ctx->status.code = 0; | 1248 ctx->status.code = 0; |
1252 ctx->status.count = 0; | 1249 ctx->status.count = 0; |
1253 ctx->status.start = NULL; | 1250 ctx->status.start = NULL; |
1254 ctx->status.end = NULL; | 1251 ctx->status.end = NULL; |
1255 ctx->state = 0; | 1252 ctx->chunked.state = 0; |
1256 | 1253 |
1257 r->upstream->process_header = ngx_http_proxy_process_status_line; | 1254 r->upstream->process_header = ngx_http_proxy_process_status_line; |
1258 r->upstream->pipe->input_filter = ngx_http_proxy_copy_filter; | 1255 r->upstream->pipe->input_filter = ngx_http_proxy_copy_filter; |
1259 r->upstream->input_filter = ngx_http_proxy_non_buffered_copy_filter; | 1256 r->upstream->input_filter = ngx_http_proxy_non_buffered_copy_filter; |
1260 r->state = 0; | 1257 r->state = 0; |
1615 | 1612 |
1616 return NGX_OK; | 1613 return NGX_OK; |
1617 } | 1614 } |
1618 | 1615 |
1619 | 1616 |
1620 static ngx_inline ngx_int_t | |
1621 ngx_http_proxy_parse_chunked(ngx_http_request_t *r, ngx_buf_t *buf) | |
1622 { | |
1623 u_char *pos, ch, c; | |
1624 ngx_int_t rc; | |
1625 ngx_http_proxy_ctx_t *ctx; | |
1626 enum { | |
1627 sw_chunk_start = 0, | |
1628 sw_chunk_size, | |
1629 sw_chunk_extension, | |
1630 sw_chunk_extension_almost_done, | |
1631 sw_chunk_data, | |
1632 sw_after_data, | |
1633 sw_after_data_almost_done, | |
1634 sw_last_chunk_extension, | |
1635 sw_last_chunk_extension_almost_done, | |
1636 sw_trailer, | |
1637 sw_trailer_almost_done, | |
1638 sw_trailer_header, | |
1639 sw_trailer_header_almost_done | |
1640 } state; | |
1641 | |
1642 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module); | |
1643 | |
1644 if (ctx == NULL) { | |
1645 return NGX_ERROR; | |
1646 } | |
1647 | |
1648 state = ctx->state; | |
1649 | |
1650 if (state == sw_chunk_data && ctx->size == 0) { | |
1651 state = sw_after_data; | |
1652 } | |
1653 | |
1654 rc = NGX_AGAIN; | |
1655 | |
1656 for (pos = buf->pos; pos < buf->last; pos++) { | |
1657 | |
1658 ch = *pos; | |
1659 | |
1660 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1661 "http proxy chunked byte: %02Xd s:%d", ch, state); | |
1662 | |
1663 switch (state) { | |
1664 | |
1665 case sw_chunk_start: | |
1666 if (ch >= '0' && ch <= '9') { | |
1667 state = sw_chunk_size; | |
1668 ctx->size = ch - '0'; | |
1669 break; | |
1670 } | |
1671 | |
1672 c = (u_char) (ch | 0x20); | |
1673 | |
1674 if (c >= 'a' && c <= 'f') { | |
1675 state = sw_chunk_size; | |
1676 ctx->size = c - 'a' + 10; | |
1677 break; | |
1678 } | |
1679 | |
1680 goto invalid; | |
1681 | |
1682 case sw_chunk_size: | |
1683 if (ch >= '0' && ch <= '9') { | |
1684 ctx->size = ctx->size * 16 + (ch - '0'); | |
1685 break; | |
1686 } | |
1687 | |
1688 c = (u_char) (ch | 0x20); | |
1689 | |
1690 if (c >= 'a' && c <= 'f') { | |
1691 ctx->size = ctx->size * 16 + (c - 'a' + 10); | |
1692 break; | |
1693 } | |
1694 | |
1695 if (ctx->size == 0) { | |
1696 | |
1697 switch (ch) { | |
1698 case CR: | |
1699 state = sw_last_chunk_extension_almost_done; | |
1700 break; | |
1701 case LF: | |
1702 state = sw_trailer; | |
1703 break; | |
1704 case ';': | |
1705 case ' ': | |
1706 case '\t': | |
1707 state = sw_last_chunk_extension; | |
1708 break; | |
1709 default: | |
1710 goto invalid; | |
1711 } | |
1712 | |
1713 break; | |
1714 } | |
1715 | |
1716 switch (ch) { | |
1717 case CR: | |
1718 state = sw_chunk_extension_almost_done; | |
1719 break; | |
1720 case LF: | |
1721 state = sw_chunk_data; | |
1722 break; | |
1723 case ';': | |
1724 case ' ': | |
1725 case '\t': | |
1726 state = sw_chunk_extension; | |
1727 break; | |
1728 default: | |
1729 goto invalid; | |
1730 } | |
1731 | |
1732 break; | |
1733 | |
1734 case sw_chunk_extension: | |
1735 switch (ch) { | |
1736 case CR: | |
1737 state = sw_chunk_extension_almost_done; | |
1738 break; | |
1739 case LF: | |
1740 state = sw_chunk_data; | |
1741 } | |
1742 break; | |
1743 | |
1744 case sw_chunk_extension_almost_done: | |
1745 if (ch == LF) { | |
1746 state = sw_chunk_data; | |
1747 break; | |
1748 } | |
1749 goto invalid; | |
1750 | |
1751 case sw_chunk_data: | |
1752 rc = NGX_OK; | |
1753 goto data; | |
1754 | |
1755 case sw_after_data: | |
1756 switch (ch) { | |
1757 case CR: | |
1758 state = sw_after_data_almost_done; | |
1759 break; | |
1760 case LF: | |
1761 state = sw_chunk_start; | |
1762 } | |
1763 break; | |
1764 | |
1765 case sw_after_data_almost_done: | |
1766 if (ch == LF) { | |
1767 state = sw_chunk_start; | |
1768 break; | |
1769 } | |
1770 goto invalid; | |
1771 | |
1772 case sw_last_chunk_extension: | |
1773 switch (ch) { | |
1774 case CR: | |
1775 state = sw_last_chunk_extension_almost_done; | |
1776 break; | |
1777 case LF: | |
1778 state = sw_trailer; | |
1779 } | |
1780 break; | |
1781 | |
1782 case sw_last_chunk_extension_almost_done: | |
1783 if (ch == LF) { | |
1784 state = sw_trailer; | |
1785 break; | |
1786 } | |
1787 goto invalid; | |
1788 | |
1789 case sw_trailer: | |
1790 switch (ch) { | |
1791 case CR: | |
1792 state = sw_trailer_almost_done; | |
1793 break; | |
1794 case LF: | |
1795 goto done; | |
1796 default: | |
1797 state = sw_trailer_header; | |
1798 } | |
1799 break; | |
1800 | |
1801 case sw_trailer_almost_done: | |
1802 if (ch == LF) { | |
1803 goto done; | |
1804 } | |
1805 goto invalid; | |
1806 | |
1807 case sw_trailer_header: | |
1808 switch (ch) { | |
1809 case CR: | |
1810 state = sw_trailer_header_almost_done; | |
1811 break; | |
1812 case LF: | |
1813 state = sw_trailer; | |
1814 } | |
1815 break; | |
1816 | |
1817 case sw_trailer_header_almost_done: | |
1818 if (ch == LF) { | |
1819 state = sw_trailer; | |
1820 break; | |
1821 } | |
1822 goto invalid; | |
1823 | |
1824 } | |
1825 } | |
1826 | |
1827 data: | |
1828 | |
1829 ctx->state = state; | |
1830 buf->pos = pos; | |
1831 | |
1832 switch (state) { | |
1833 | |
1834 case sw_chunk_start: | |
1835 ctx->length = 3 /* "0" LF LF */; | |
1836 break; | |
1837 case sw_chunk_size: | |
1838 ctx->length = 2 /* LF LF */ | |
1839 + (ctx->size ? ctx->size + 4 /* LF "0" LF LF */ : 0); | |
1840 break; | |
1841 case sw_chunk_extension: | |
1842 case sw_chunk_extension_almost_done: | |
1843 ctx->length = 1 /* LF */ + ctx->size + 4 /* LF "0" LF LF */; | |
1844 break; | |
1845 case sw_chunk_data: | |
1846 ctx->length = ctx->size + 4 /* LF "0" LF LF */; | |
1847 break; | |
1848 case sw_after_data: | |
1849 case sw_after_data_almost_done: | |
1850 ctx->length = 4 /* LF "0" LF LF */; | |
1851 break; | |
1852 case sw_last_chunk_extension: | |
1853 case sw_last_chunk_extension_almost_done: | |
1854 ctx->length = 2 /* LF LF */; | |
1855 break; | |
1856 case sw_trailer: | |
1857 case sw_trailer_almost_done: | |
1858 ctx->length = 1 /* LF */; | |
1859 break; | |
1860 case sw_trailer_header: | |
1861 case sw_trailer_header_almost_done: | |
1862 ctx->length = 2 /* LF LF */; | |
1863 break; | |
1864 | |
1865 } | |
1866 | |
1867 return rc; | |
1868 | |
1869 done: | |
1870 | |
1871 return NGX_DONE; | |
1872 | |
1873 invalid: | |
1874 | |
1875 return NGX_ERROR; | |
1876 } | |
1877 | |
1878 | |
1879 static ngx_int_t | 1617 static ngx_int_t |
1880 ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) | 1618 ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) |
1881 { | 1619 { |
1882 ngx_int_t rc; | 1620 ngx_int_t rc; |
1883 ngx_buf_t *b, **prev; | 1621 ngx_buf_t *b, **prev; |
1899 b = NULL; | 1637 b = NULL; |
1900 prev = &buf->shadow; | 1638 prev = &buf->shadow; |
1901 | 1639 |
1902 for ( ;; ) { | 1640 for ( ;; ) { |
1903 | 1641 |
1904 rc = ngx_http_proxy_parse_chunked(r, buf); | 1642 rc = ngx_http_parse_chunked(r, buf, &ctx->chunked); |
1905 | 1643 |
1906 if (rc == NGX_OK) { | 1644 if (rc == NGX_OK) { |
1907 | 1645 |
1908 /* a chunk has been parsed successfully */ | 1646 /* a chunk has been parsed successfully */ |
1909 | 1647 |
1950 /* STUB */ b->num = buf->num; | 1688 /* STUB */ b->num = buf->num; |
1951 | 1689 |
1952 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0, | 1690 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0, |
1953 "input buf #%d %p", b->num, b->pos); | 1691 "input buf #%d %p", b->num, b->pos); |
1954 | 1692 |
1955 if (buf->last - buf->pos >= ctx->size) { | 1693 if (buf->last - buf->pos >= ctx->chunked.size) { |
1956 | 1694 |
1957 buf->pos += ctx->size; | 1695 buf->pos += ctx->chunked.size; |
1958 b->last = buf->pos; | 1696 b->last = buf->pos; |
1959 ctx->size = 0; | 1697 ctx->chunked.size = 0; |
1960 | 1698 |
1961 continue; | 1699 continue; |
1962 } | 1700 } |
1963 | 1701 |
1964 ctx->size -= buf->last - buf->pos; | 1702 ctx->chunked.size -= buf->last - buf->pos; |
1965 buf->pos = buf->last; | 1703 buf->pos = buf->last; |
1966 b->last = buf->last; | 1704 b->last = buf->last; |
1967 | 1705 |
1968 continue; | 1706 continue; |
1969 } | 1707 } |
1980 | 1718 |
1981 if (rc == NGX_AGAIN) { | 1719 if (rc == NGX_AGAIN) { |
1982 | 1720 |
1983 /* set p->length, minimal amount of data we want to see */ | 1721 /* set p->length, minimal amount of data we want to see */ |
1984 | 1722 |
1985 p->length = ctx->length; | 1723 p->length = ctx->chunked.length; |
1986 | 1724 |
1987 break; | 1725 break; |
1988 } | 1726 } |
1989 | 1727 |
1990 /* invalid response */ | 1728 /* invalid response */ |
1995 return NGX_ERROR; | 1733 return NGX_ERROR; |
1996 } | 1734 } |
1997 | 1735 |
1998 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1736 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1999 "http proxy chunked state %d, length %d", | 1737 "http proxy chunked state %d, length %d", |
2000 ctx->state, p->length); | 1738 ctx->chunked.state, p->length); |
2001 | 1739 |
2002 if (b) { | 1740 if (b) { |
2003 b->shadow = buf; | 1741 b->shadow = buf; |
2004 b->last_shadow = 1; | 1742 b->last_shadow = 1; |
2005 | 1743 |
2092 ll = &cl->next; | 1830 ll = &cl->next; |
2093 } | 1831 } |
2094 | 1832 |
2095 for ( ;; ) { | 1833 for ( ;; ) { |
2096 | 1834 |
2097 rc = ngx_http_proxy_parse_chunked(r, buf); | 1835 rc = ngx_http_parse_chunked(r, buf, &ctx->chunked); |
2098 | 1836 |
2099 if (rc == NGX_OK) { | 1837 if (rc == NGX_OK) { |
2100 | 1838 |
2101 /* a chunk has been parsed successfully */ | 1839 /* a chunk has been parsed successfully */ |
2102 | 1840 |
2114 b->memory = 1; | 1852 b->memory = 1; |
2115 | 1853 |
2116 b->pos = buf->pos; | 1854 b->pos = buf->pos; |
2117 b->tag = u->output.tag; | 1855 b->tag = u->output.tag; |
2118 | 1856 |
2119 if (buf->last - buf->pos >= ctx->size) { | 1857 if (buf->last - buf->pos >= ctx->chunked.size) { |
2120 buf->pos += ctx->size; | 1858 buf->pos += ctx->chunked.size; |
2121 b->last = buf->pos; | 1859 b->last = buf->pos; |
2122 ctx->size = 0; | 1860 ctx->chunked.size = 0; |
2123 | 1861 |
2124 } else { | 1862 } else { |
2125 ctx->size -= buf->last - buf->pos; | 1863 ctx->chunked.size -= buf->last - buf->pos; |
2126 buf->pos = buf->last; | 1864 buf->pos = buf->last; |
2127 b->last = buf->last; | 1865 b->last = buf->last; |
2128 } | 1866 } |
2129 | 1867 |
2130 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1868 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |